martes, 19 de enero de 2016

SQL Server - Usos no deseados de la operación UNION

Hace pocos días me topé en el trabajo con código SQL embebido, escrito por otro programador tiempo atrás, en donde hacía un uso indebido de la operación UNION. En el ejemplo en cuestión, se quería realizar el promedio de los valores de una columna TOTAL y, si bien todos los valores eran positivos, al sumarlos había que tener en cuenta la columna TIPO para sumarlos o restarlos al resultado, puesto que dependían de esta columna, para saber si eran de tipo créditos o débitos. Es decir, éstos valores dependían de una condición que los separaban en negativos y positivos.

Cuando veo como estaba escrito el código SQL me doy cuenta que el resultado no iba a ser el esperado porque se estaba separando la condición con una operación UNION 
Escribo la consulta en cuestión:


SELECT CantidadCasos = COUNT(*)
      ,Promedio = SUM(Total) / COUNT(*)
FROM Pedidos
UNION ALL
SELECT CantidadCasos = COUNT(*)
      ,Promedio = SUM(Total * (-1)) / COUNT(*)
FROM FACT0003
GO




El conjunto de resultados sería el siguiente:


Como se ve, esto nos da un registro por cada consulta (SELECT) en el caso que se den ambas condiciones (en el caso que la unión sea válida para ambos casos) y por ende, el promedio tampoco va a ser el correcto.

La forma correcta sería tratarlo con una expresión del tipo condicional, CASE o IF, teniendo en cuenta como se hace uso de las consultas de agregado (SUM(), COUNT(), etc) que es en donde muchos se equivocan o creen que no se puede realizar este tipo de consultas. Si prestan atención, el condicional siempre está dentro del agregado (en este caso el CASE dentro del SUM():


SELECT CantidadCasos = COUNT(*)
      ,Importe = SUM(CASE Tipo WHEN 'N' THEN Total * (-1) ELSE Total END) / COUNT(*)
FROM Pedidos
GO



El conjunto de resultados, para la consulta anterior, sería el siguiente:



Ahora sí, el resultado es el esperado.

No hay comentarios.:

Publicar un comentario