ProgramaciónAnalista SQL

¿Cómo implementar una agregación eficiente con filtrado por niveles utilizando funciones de ventana y agrupaciones en SQL? ¿Cuáles son las diferencias entre los enfoques y qué errores cometen frecuentemente los desarrolladores?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

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.

  • Agrupación a través de GROUP BY agrega solo por los campos seleccionados; se puede excluir la influencia de filas "externas" solo a través de un filtro previo (WHERE).
  • Funciones de ventana permiten calcular agregados sobre fragmentos específicos de datos, aplicando filtros sobre el conjunto de resultados (por ejemplo, solo entre filas del mismo grupo).

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.

Pregunta capciosa.

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;

Ejemplos de errores reales debido a la falta de conocimiento de los matices del tema.


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.