我正在创建一个SQL查询,它将根据两个聚合函数的值从表中提取记录。这些聚合函数从同一个表中提取数据,但具有不同的过滤条件。我遇到的问题是SUM的结果比我只包含一个SUM函数要大得多。我知道我可以使用临时表创建此查询,但我只是想知道是否有一个只需要一个查询的优雅解决方案。
我已经创建了一个简化版本来演示这个问题。以下是表格结构:
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
以下是查询:
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
非常感谢任何见解。
答案 0 :(得分:23)
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
编辑:
这不是什么大问题,但我讨厌重复条件,所以我们可以重构:
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
这样一来,如果你改变你的情况,它只在一个地方。
答案 1 :(得分:4)
分别对不同的东西进行分组,加入群组。
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
此外,如果只有SQL关键字是上限而其余的不是,则可读性会增加。 IMHO。
答案 2 :(得分: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
答案 3 :(得分:0)
值得注意的是,您实际上不必在0
表达式中为ELSE
的情况下的CASE
提供一个NULL
值,如Jeremy's answer所示。由于聚合函数不会聚合CASE
值,因此您可以将其保留为空,而仅使用SELECT
e.empid,
SUM(CASE WHEN <something> THEN atotal.hours_absent END) AS absent_total,
SUM(CASE WHEN <something> THEN ayear.hours_absent END) AS absent_year
FROM ...
表达式指定要在聚合中包括的值,例如
{{1}}