¿Se puede agrupar por rangos de valores?

Esta mañana en clase, me habéis preguntado si al agrupar podemos utilizar rangos de valores para definir los grupos. Mi respuesta ha sido que no. Los grupos se definen en base a valores concretos de los componentes del criterio de agrupación. Pero podemos aplicar un truquillo para conseguir esa agrupación por rangos (a esta técnica se llama SQL Binning).

Se trata de usar una estructura case para asignar una "etiqueta" a cada rango de valores y, posteriormente agrupar en función de los valores de esa "etiqueta".

Para ilustrar esta idea consideremos este ejemplo:

Determinar cuántas asignaturas baratas, normales y caras hay en la BD (‘barata’ si su precio por crédito es menor de 5€, ‘normal’ si está entre 5€-10€ y ‘cara’ si es mayor de 10€)

En primer lugar, os muestro cómo asignaríamos esas etiquetas a las asignaturas (este es un ejercicio que ya hicimos en clase):

select IDASIGNATURA,
       NOMBRE,
       COSTEBASICO / CREDITOS "coste por credito",
       case
           when COSTEBASICO / CREDITOS < 5 then 'barata'
           when COSTEBASICO / CREDITOS between 5 and 10 then 'normal'
           when COSTEBASICO / CREDITOS > 10 then 'cara'
           end                tipo
from asignatura;
+--------------+--------------------+-------------------+--------+
| IDASIGNATURA | NOMBRE             | coste por credito | tipo   |
+--------------+--------------------+-------------------+--------+
| 000115       | Seguridad Vial     |           6.66667 | normal |
| 000116       | Inglés técnico     |          13.33333 | cara   |
| 130044       | Estadística        |          15.00000 | cara   |
| 130113       | Programación I     |           6.66667 | normal |
| 130122       | Análisis II        |           7.77778 | normal |
| 150001       | Derecho            |           7.36842 | normal |
| 150212       | Química Física     |          15.55556 | cara   |
| 160002       | Contabilidad       |          11.66667 | cara   |
| 160003       | Gestión de empresa |          12.85714 | cara   |
+--------------+--------------------+-------------------+--------+

Podemos usar esas “etiquetas” de tipo para agrupar. Eso es lo que haremos para resolver la consulta propuesta. Generaremos un grupo con aquellas tuplas para las cuales el case evalúe al valor 'barata' (no hay ninguna tupla); otro grupo para las tuplas en las que el cse valga 'normal'; y otro para las tuplas de tipo 'cara':

select case
           when COSTEBASICO / CREDITOS < 5 then 'barata'
           when COSTEBASICO / CREDITOS between 5 and 10 then 'normal'
           when COSTEBASICO / CREDITOS > 10 then 'cara'
           end                tipo, 
       count(*) N
from asignatura
group by case
           when COSTEBASICO / CREDITOS < 5 then 'barata'
           when COSTEBASICO / CREDITOS between 5 and 10 then 'normal'
           when COSTEBASICO / CREDITOS > 10 then 'cara'
           end;

Que devuelve

+--------+---+
| tipo   | N |
+--------+---+
| normal | 4 |
| cara   | 5 |
+--------+---+

Si estuviésemos usando MySQL, la consulta anterior podría simplificarse usando el alias "tipo":

select case
           when COSTEBASICO / CREDITOS < 5 then 'barata'
           when COSTEBASICO / CREDITOS between 5 and 10 then 'normal'
           when COSTEBASICO / CREDITOS > 10 then 'cara'
           end                tipo, 
       count(*) N
from asignatura
group by tipo;

No hay comentarios:

Publicar un comentario