Saltar al contenido

Oracle: ¿cómo “agrupar por” en un rango?

Agradeceríamos tu apoyo para extender nuestras reseñas sobre las ciencias de la computación.

Solución:

SELECT CASE 
         WHEN age <= 10 THEN '1-10' 
         WHEN age <= 20 THEN '11-20' 
         ELSE '21+' 
       END AS age, 
       COUNT(*) AS n
FROM age
GROUP BY CASE 
           WHEN age <= 10 THEN '1-10' 
           WHEN age <= 20 THEN '11-20' 
           ELSE '21+' 
         END

Tratar:

select to_char(floor(age/10) * 10) || '-' 
|| to_char(ceil(age/10) * 10 - 1)) as age, 
count(*) as n from tbl group by floor(age/10);

Lo que está buscando, es básicamente los datos de un histograma.

Tendría la edad (o rango de edad) en el eje x y el conteo n (o frecuencia) en el eje y.

En la forma más simple, uno podría simplemente contar el número de cada valor de edad distinto como ya describió:

SELECT age, count(*)
FROM tbl
GROUP BY age

Sin embargo, cuando hay demasiados valores diferentes para el eje x, es posible que desee crear grupos (o clústeres o cubos). En su caso, agrupa por un rango constante de 10.

Podemos evitar escribir un WHEN ... THEN línea para cada rango - podría haber cientos si no fuera por la edad. En cambio, el enfoque de @MatthewFlaschen es preferible por las razones mencionadas por @NitinMidha.

Ahora construyamos el SQL...

Primero, necesitamos dividir las edades en grupos de rango de 10 así:

  • 0-9
  • 10-19
  • 20 - 29
  • etc.

Esto se puede lograr dividiendo la columna de edad por 10 y luego calculando el PISO del resultado:

FLOOR(age/10)

"FLOOR devuelve el entero más grande igual o menor que n" http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions067.htm#SQLRF00643

Luego tomamos el SQL original y lo reemplazamos edad con esa expresión:

SELECT FLOOR(age/10), count(*)
FROM tbl
GROUP BY FLOOR(age/10)

Esto está bien, pero todavía no podemos ver el rango. En cambio, solo vemos los valores mínimos calculados que son 0, 1, 2 ... n.

Para obtener el límite inferior real, debemos multiplicarlo nuevamente por 10 para obtener 0, 10, 20 ... n:

FLOOR(age/10) * 10

También necesitamos el límite superior de cada rango que es inferior enlazado + 10 - 1 o

FLOOR(age/10) * 10 + 10 - 1

Finalmente, concatenamos ambos en un string Me gusta esto:

TO_CHAR(FLOOR(age/10) * 10) || '-' || TO_CHAR(FLOOR(age/10) * 10 + 10 - 1)

Esto crea '0-9', '10-19', '20-29' etc.

Ahora nuestro SQL se ve así:

SELECT 
TO_CHAR(FLOOR(age/10) * 10) || ' - ' || TO_CHAR(FLOOR(age/10) * 10 + 10 - 1),
COUNT(*)
FROM tbl
GROUP BY FLOOR(age/10)

Finalmente, aplique un orden y alias de columna agradables:

SELECT 
TO_CHAR(FLOOR(age/10) * 10) || ' - ' || TO_CHAR(FLOOR(age/10) * 10 + 10 - 1) AS range,
COUNT(*) AS frequency
FROM tbl
GROUP BY FLOOR(age/10)
ORDER BY FLOOR(age/10)

Sin embargo, en escenarios más complejos, es posible que estos rangos no se agrupen en partes constantes de tamaño 10, sino que necesiten un agrupamiento dinámico. Oracle tiene funciones de histograma más avanzadas incluidas, consulte http://docs.oracle.com/cd/E16655_01/server.121/e15858/tgsql_histo.htm#TGSQL366

Créditos a @MatthewFlaschen por su enfoque; Solo expliqué los detalles.

Si para ti ha sido provechoso este artículo, agradeceríamos que lo compartas con más desarrolladores de este modo nos ayudas a dar difusión a este contenido.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *