Para construir agregaciones de manera efectiva con filtrado por "niveles" (por ejemplo, filtrar primero y luego calcular sumas por grupos, y luego sobre todo el conjunto), se utilizan funciones de ventana (OVER()) y GROUP BY anidados.
Ejemplo: Encontraremos la suma máxima de pedidos por cada gerente, pero solo entre los pedidos con estado 'paid', y luego mostraremos el nombre del gerente con el máximo absoluto entre todos.
WITH PaidOrders AS ( SELECT ManagerID, SUM(OrderAmount) AS TotalPaid FROM Orders WHERE Status = 'paid' GROUP BY ManagerID ), WithMax AS ( SELECT *, MAX(TotalPaid) OVER() AS MaxTotalPaid FROM PaidOrders ) SELECT ManagerID, TotalPaid FROM WithMax WHERE TotalPaid = MaxTotalPaid;
Este enfoque (CTE + funciones de ventana) permite implementar filtrado y agregación en múltiples niveles.
Trampa: "¿Cuál es la diferencia entre ejecutar un filtro WHERE antes de la agrupación (GROUP BY) y aplicar HAVING después? ¿Qué problemas puede causar esto en los informes?"
Respuesta: WHERE descarta filas incluso antes de la agrupación, es decir, proporciona un conjunto de entrada estricto. HAVING filtra grupos agregados, por lo que puede temporalmente "dejar" filas extra si el filtro no está lógicamente alineado. Un lugar incorrecto para el filtro a menudo conduce a errores en los agregados finales o a resultados incorrectos en los informes.
-- Obtenemos la suma solo de 'paid', a través de WHERE SELECT ManagerID, SUM(OrderAmount) FROM Orders WHERE Status = 'paid' GROUP BY ManagerID; -- O calculamos sumas de todos y luego cortamos con HAVING SELECT ManagerID, SUM(OrderAmount) FROM Orders GROUP BY ManagerID HAVING SUM(OrderAmount) > 1000;
Historia
Proyecto: Informes de ventas, auditoría de verificación.
Error: El desarrollador utilizó HAVING Status='paid' en lugar de WHERE, los agregados incluían erróneamente pedidos no pagados, lo que llevó a cálculos incorrectos de los KPI anuales del personal.
Historia
Proyecto: Análisis bancario.
Error: Intentaron aplicar una función de ventana a una agregación compleja sin PARTITION BY, lo que hizo que los agregados se calcularan sobre toda la tabla en lugar de sobre el grupo. El presupuesto del departamento fue calculado incorrectamente, tuvo que ser restaurado manualmente.
Historia
Proyecto: Tienda en línea, estadísticas de pedidos.
Error: No se tuvo en cuenta la inserción de funciones de ventana en una subconsulta durante la optimización, lo que llevó a que el servidor procesara los datos múltiples veces, y la consulta se volvió 20 veces más lenta que si se hubiera realizado con un simple GROUP BY doble.