2010-04-16 15 views
9

Estoy trabajando en la creación de una consulta SQL que extraerá registros de una tabla en función del valor de dos funciones agregadas. Estas funciones agregadas están extrayendo datos de la misma tabla, pero con diferentes condiciones de filtro. El problema con el que me encuentro es que los resultados de las SUM son mucho más grandes que si solo incluyese una función SUMA. Sé que puedo crear esta consulta utilizando tablas temporales, pero me pregunto si existe una solución elegante que requiera solo una consulta.Múltiples funciones agregadas en una consulta SQL de la misma tabla usando condiciones diferentes

He creado una versión simplificada para demostrar el problema. Aquí están las estructuras de tabla:

EMPLOYEE TABLE 

EMPID 
1 
2 
3 

ABSENCE TABLE 

EMPID DATE  HOURS_ABSENT 
1  6/1/2009 3 
1  9/1/2009 1 
2  3/1/2010 2 

Y aquí es la consulta:

SELECT 
    E.EMPID 
    ,SUM(ATOTAL.HOURS_ABSENT) AS ABSENT_TOTAL 
    ,SUM(AYEAR.HOURS_ABSENT) AS ABSENT_YEAR 

FROM 
    EMPLOYEE E 

    INNER JOIN ABSENCE ATOTAL ON 
     ATOTAL.EMPID = E.EMPID 

    INNER JOIN ABSENCE AYEAR ON 
     AYEAR.EMPID = E.EMPID 

WHERE 
    AYEAR.DATE > '1/1/2010' 

GROUP BY 
    E.EMPID 

HAVING 
    SUM(ATOTAL.HOURS_ABSENT) > 10 
    OR SUM(AYEAR.HOURS_ABSENT) > 3 

Cualquier idea sería muy apreciada.

+0

Es un poco confuso. En base a los datos dados, ¿cuál es su resultado esperado? – Raja

Respuesta

19
SELECT 
    E.EMPID 
    ,SUM(ABSENCE.HOURS_ABSENT) AS ABSENT_TOTAL 
    ,SUM(case when year(Date) = 2010 then ABSENCE.HOURS_ABSENT else 0 end) AS ABSENT_YEAR 

FROM 
    EMPLOYEE E 

    INNER JOIN ABSENCE ON 
     ABSENCE.EMPID = E.EMPID 

GROUP BY 
    E.EMPID 

HAVING 
    SUM(ATOTAL.HOURS_ABSENT) > 10 
    OR SUM(case when year(Date) = 2010 then ABSENCE.HOURS_ABSENT else 0 end) > 3 

edición:

No es un gran problema, pero no me gusta condiciones de repetición para que pudiéramos refactor como:

Select * From 
(
    SELECT 
     E.EMPID 
     ,SUM(ABSENCE.HOURS_ABSENT) AS ABSENT_TOTAL 
     ,SUM(case when year(Date) = 2010 then ABSENCE.HOURS_ABSENT else 0 end) AS ABSENT_YEAR 

    FROM 
     EMPLOYEE E 

     INNER JOIN ABSENCE ON 
      ABSENCE.EMPID = E.EMPID 

    GROUP BY 
     E.EMPID 
    ) EmployeeAbsences 
    Where ABSENT_TOTAL > 10 or ABSENT_YEAR > 3 

De esta manera, si cambia su condición caso, es en una mancha solo

+0

¡Muchas gracias! Me presentaste el "caso cuando" ... ¡me sacaste del gran problema que estaba teniendo! – user979051

0
SELECT E.EMPID , sum(ABSENT_TOTAL) , sum(ABSENT_YEAR) 
FROM 
(SELECT 
    E.EMPID 
    ,SUM(ATOTAL.HOURS_ABSENT) AS ABSENT_TOTAL 
    ,0 AS ABSENT_YEAR 

FROM 
    EMPLOYEE E 

    INNER JOIN ABSENCE ATOTAL ON 
     ATOTAL.EMPID = E.EMPID 
WHERE 
    AYEAR.DATE > '1/1/2010' 

GROUP BY 
    E.EMPID 

HAVING 
    SUM(ATOTAL.HOURS_ABSENT) > 10 

UNION ALL 

SELECT 0  
    ,SUM(AYEAR.HOURS_ABSENT) 
FROM 
    EMPLOYEE E  

     INNER JOIN ABSENCE AYEAR ON 
     AYEAR.EMPID = E.EMPID 

GROUP BY 
    E.EMPID 

HAVING 
    SUM(AYEAR.HOURS_ABSENT) > 3) a 

    GROUP BY A.EMPID 
4

Agrupe cosas diferentes por separado, únase a grupos.

SELECT 
    T.EMPID 
    ,T.ABSENT_TOTAL 
    ,Y.ABSENT_YEAR 
FROM 
    (
    SELECT 
     E.EMPID 
     ,SUM(A.HOURS_ABSENT) AS ABSENT_TOTAL 
    FROM 
     EMPLOYEE E 
     INNER JOIN ABSENCE A ON A.EMPID = E.EMPID 
    GROUP BY 
     E.EMPID 
    ) AS T 
    INNER JOIN 
    (
    SELECT 
     E.EMPID 
     ,SUM(A.HOURS_ABSENT) AS ABSENT_YEAR 
    FROM 
     EMPLOYEE E 
     INNER JOIN ABSENCE A ON A.EMPID = E.EMPID 
    WHERE 
     A.DATE > '1/1/2010' 
    GROUP BY 
     E.EMPID 
    ) AS Y 
    ON T.EMPLID = Y.EMPLID 
WHERE 
    ABSENT_TOTAL > 10 OR ABSENT_YEAR > 3 

Además, si solo las palabras clave SQL son mayúsculas y el resto no, la legibilidad aumenta. EN MI HUMILDE OPINIÓN.

Cuestiones relacionadas