Obtener la MODA de un grupo
En el desarrollo de nuestro último proyecto nos hemos encontrado ante la necesidad de saber para cada día del mes a qué hora ha habido el mayor número de llamadas, o lo que es lo mismo, cuál es la hora punta de llamadas de cada día.
En el fondo, si lo tratáramos como una muestra estadística sería obtener que hora es la Moda para cada día.
Supongamos que tenemos la siguiente consulta:
Select DiaLlamada, HoraLlamada, Count(*) as Total
From Llamadas
Where EjercicioLlamada = 2016 and MesLlamada = 9
Group by DiaLlamada, HoraLlamada
Order by 1, 3 desc
Como lo que queremos es el primer registro de cada una de las categorías, no nos sirve añadir una clausula tipo TOP a la sentencia anterior, puesto que nos devolvería los n primeros resultados que serían siempre del mismo día.
Si hubieramos ordenado por número de llamadas independientemente del día tampoco podríamos utilizar la clausula TOP puesto que podrían haber registros del mismo día (si el mismo día hubiera habido muchas llamadas a varias horas)
Solución
Select DiaLlamada, HoraLlamada, count(*) as NumLlamadas,
ROW_NUMBER() OVER (PARTITION BY DiaLlamada ORDER BY count(*) DESC) AS RN
From Llamadas
Where EjercicioLlamada = 2016 and MesLlamada = 9
Group by DiaLlamada, HoraLlamada
With Lista AS
(
Select DiaLlamada, HoraLlamada, count(*) as NumLlamadas,
ROW_NUMBER() OVER (PARTITION BY DiaLlamada ORDER BY count(*) DESC) AS RN
From Llamadas
Where EjercicioLlamada = 2016 and MesLlamada = 9
Group by DiaLlamada, HoraLlamada
)
Select *
FROM Lista
Where RN = 1;
Es posible que dos franjas horarias tengan el mismo número de llamadas. En nuestro caso no importaba cual de ellas obtener. Si fuese importante, se debería modificar la consulta para ordenar según el criterio necesario.
Otras funciones de categorización
Además de Row_number, existen otras alternativas para ordenar y categorizar resultados, os dejamos la definición y un ejemplo de utilización de cada una de ellas.
ROW_NUMBER es una función de categoría y como tal, es una función no determinista. Si la expresión de ordenación no es única, cada vez que se ejecute la consulta podrá asignar posiciones diferentes para cualquier fila donde la expresión de ordenación sea la misma. En cambio, si esa expresión de ordenación es única, cada fila obtendrá una número de fila única.
RANK – A diferencia de ROW_NUMBER, no asigna una numeración única cuando dos registros comparten la misma posición. Es decir, podrán haber tantas posiciones 1ª, 2ª,… como registros compartan esa posición.
DENSE_RANK – Su funcionamiento es similar a RANK, aunque a diferencia de ese, sí asigna números contiguos.
NTILE – Según el parámetro que le asignemos dividirá los registros en tantos grupos, repitiendo la numeración.
Podéis comprobar sus diferencias en el resultado de la consulta que hemos estado utilizando:
Select DiaLlamada, HoraLlamada, count(*) as NumLlamadas,
ROW_NUMBER() OVER (PARTITION BY DiaLlamada ORDER BY count(*) DESC) AS "Row Number",
RANK() OVER (PARTITION BY DiaLlamada ORDER BY count(*) DESC) AS "Rank",
DENSE_RANK() OVER (PARTITION BY DiaLlamada ORDER BY count(*) DESC) AS "Dense Rank",
NTILE (4) OVER (PARTITION BY DiaLlamada ORDER BY count(*) DESC) AS "Periodo"
From Llamadas
Where EjercicioLlamada = 2016 AND MesLlamada = 9 AND CodigoGrupo = 2
Group By DiaLlamada, HoraLlamada
Podéis obtener más información en los siguientes enlaces:
Quieres compartir tus impresiones?
Tu dirección de correo no será publicada. Los campos obligatorios se marcan con *