ProgramaciónDesarrollador Backend, Analista BI

¿Cómo implementar una agregación confiable con condiciones únicas (agregación condicional) en SQL al construir informes con varios filtros? ¿Qué matices existen al mezclar HAVING, CASE y funciones de agregación?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

La agregación condicional es una tarea clásica para la elaboración de informes. Originalmente, se creaban consultas separadas con filtros para contar diferentes indicadores. Pronto apareció una solución más compacta: la agregación condicional utilizando CASE dentro de funciones de agregación (por ejemplo, SUM(CASE WHEN ...)). El problema se manifiesta al combinar filtros, agrupaciones y encabezados de totales: se pueden obtener fácilmente sumas incorrectas o interpretar erróneamente el resultado.

Solución: utilizar la agregación condicional dentro de funciones de agregación. Por ejemplo, se necesita mostrar para todos los empleados el número de pedidos "en proceso" y "completados":

SELECT employee_id, SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END) as processing_count, SUM(CASE WHEN status = 'done' THEN 1 ELSE 0 END) as done_count FROM Orders GROUP BY employee_id;

Características clave:

  • Independientemente del filtro WHERE, todas las sumas necesarias se calculan en una sola consulta.
  • CASE dentro de SUM permite construir informes complejos de múltiples indicadores.
  • HAVING se aplica a los datos ya agregados, para la post-filtración del resultado de la agrupación.

Preguntas engañosas.

¿Qué sucederá si la condición CASE devuelve NULL en lugar de 0?

La función de agregación SUM ignora NULL. Por lo tanto, si se escribe CASE WHEN ... THEN 1 END, las filas omitidas no se contabilizarán. Es mejor siempre establecer explícitamente ELSE 0.

SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END)

¿Puede un filtro WHERE cambiar la suma total por estados en la agregación condicional?

Sí: si el WHERE principal limita la selección (por ejemplo, WHERE region = 'west'), los conteos se realizarán solo en los datos filtrados. Para totales globales, utiliza subconsultas o quita el filtro.

¿Se puede utilizar HAVING para filtrar filas antes de la agrupación?

No. HAVING filtra datos ya agrupados por agregados. La filtración de filas originales se realiza a través de WHERE.

Errores típicos y anti-patrones

  • Falta ELSE, CASE devuelve NULL, los totales son incorrectos.
  • Mezclan WHERE y HAVING, obteniendo filas incorrectas.
  • Usan varias consultas en lugar de una única con CASE.

Ejemplo de la vida real

Caso negativo

En el informe de análisis se utilizó:

SUM(CASE WHEN status = 'approved' THEN 1 END)

Hubo muchos NULL, los totales finales fueron subestimados. Debido al filtro WHERE, parte de las filas necesarias se perdieron.

Ventajas:

  • El código es corto.

Desventajas:

  • Resultados incorrectos, el informe se explicó mal al negocio.

Caso positivo

Se utilizó:

SUM(CASE WHEN status = 'approved' THEN 1 ELSE 0 END)

El código se mantuvo en una única consulta, los filtros en el total se realizaron a través de HAVING.

Ventajas:

  • Indicadores correctos y transparentes.
  • Fácil añadir un nuevo estado.

Desventajas:

  • Las consultas se vuelven más largas, se requiere cuidado con los filtros.