Se puede usar case para contar/sumar cosas que cumplan una determinada condición

Aunque la mejor forma de hacer consultas con funciones de agregación (cuenta, suma…) es usando group by, en ocasiones basta con usar una cláusula case dentro de la función de agregación. 

La condición de la cláusula case incluirá en el cálculo los valores que cumplan la condición y excluirá el resto. En las prácticas hay varios ejercicios de este tipo. Como muestra, supongamos la siguiente tabla llamada Trabaja:

+-----------+----------+-------+
| Empleado  | Proyecto | Horas |
+-----------+----------+-------+
| 123456789 |        1 | 32.50 |
| 123456789 |        2 |  7.50 |
| 333445555 |        2 | 10.00 |
| 333445555 |        3 | 10.00 |
| 333445555 |       10 | 10.00 |
| 333445555 |       20 | 10.00 |
| 453453453 |        1 | 20.00 |
| 453453453 |        2 | 20.00 |
| 453453453 |      400 |  NULL |
| 555555555 |      400 | 40.00 |
| 555555555 |      500 | 40.00 |
| 666884444 |        3 | 40.00 |
| 888665555 |       20 |  1.00 |
| 987654321 |       20 | 15.00 |
| 987654321 |       30 | 20.00 |
| 987987987 |       10 | 35.00 |
| 987987987 |       30 |  5.00 |
| 999887777 |       10 | 10.00 |
| 999887777 |       30 | 30.00 |
+-----------+----------+-------+

Podemos resolver el siguiente ejercicio: "Calcular qué empleado invierte más horas en proyectos con códigos entre 10 y 30 ¿el empleado 333445555 o el 987654321? Además, incluir en el resultado el número de horas de cada empleado en esos proyectos".

select sum(case when empleado = '333445555' then horas end) "Horas de 333445555",
       sum(case when empleado = '987654321' then horas end) "Horas de 987654321",
       case
           when sum(case when empleado = '333445555' then horas end) >
                sum(case when empleado = '987654321' then horas end)
               then '333445555'
           else '987654321'
       end as "El que más horas"
from trabaja
where proyecto between 10 and 30;

Fíjate en que en el where de la consulta seleccionamos los proyectos con códigos entre 10 y 30.

+-----------+----------+-------+
| Empleado  | Proyecto | Horas |
+-----------+----------+-------+
| 333445555 |       10 | 10.00 |
| 987654321 |       30 | 20.00 |
| 987987987 |       10 | 35.00 |
| 987987987 |       30 |  5.00 |
| 999887777 |       10 | 10.00 |
| 999887777 |       30 | 30.00 |
+-----------+----------+-------+

Como ves, en estos proyectos trabajan vario empleados, pero a nosotros nos están preguntando por dos en concreto: el 333445555 y el 987654321. Podemos usar la expresión case when empleado = '333445555' then horas end para que cuando el valor del campo empleado en una fila sea '333445555' se devuelva el valor del campo horas de esa fila; y cuando no sea '333445555', no devuelva nada (por eso el case solo tiene una cláusula when y no tiene else).

+-----------+----------+-------+
| Empleado  | Proyecto | Horas |   case when empleado = '333445555' then horas end  
+-----------+----------+-------+
| 333445555 |       10 | 10.00 |  ---> 10
| 987654321 |       30 | 20.00 |  ---> null
| 987987987 |       10 | 35.00 |  ---> null
| 987987987 |       30 |  5.00 |  ---> null
| 999887777 |       10 | 10.00 |  ---> null
| 999887777 |       30 | 30.00 |  ---> null
+-----------+----------+-------+

Si aplicamos la función de agrupación sum a esa expresión case, lograremos sumar todos los valores de horas de las filas que tengan como valor de campo empleado el '333445555': sum(case when empleado = '333445555' then horas end). Es decir, tenemos la suma de las horas dedicadas por el empleado '333445555' en los proyectos con códigos entre 10 y 30. Lo mismo podemos hacer para el empleado '987654321'. Lo único que queda por hacer es comparar ambos valores, para lo cual usamos la tercera expresión de la consulta mostrada anteriormente: un case que compara las dos sumas anteriores.

Aunque la estructura case sea muy útil, no siempre conviene aplicarla. En esta entrada puedes leer algunos ejemplos de casos en los que no es adecuada.

NOTA: Como complemento a lo que aquí se recoge, puedes considerar de interés esta otra lección aprendida: Uso de CASE como si fuese GROUP BY

No hay comentarios:

Publicar un comentario