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.