I'm working on creating a SQL query that will pull records from a table based on the value of two aggregate functions. These aggregate functions are pulling data from the same table, but with different filter conditions. The problem that I run into is that the results of the SUMs are much larger than if I only include one SUM function. I know that I can create this query using temp tables, but I'm just wondering if there is an elegant solution that requires only a single query.
我正在创建一个SQL查询,该查询将根据两个聚合函数的值从表中提取记录。这些聚合函数从同一个表中提取数据,但是使用不同的过滤条件。我遇到的问题是,这些求和的结果比只包含一个和函数的结果要大得多。我知道我可以使用临时表创建这个查询,但我想知道是否有一种优雅的解决方案只需要一个查询。
I've created a simplified version to demonstrate the issue. Here are the table structures:
我创建了一个简化版本来演示这个问题。下面是表格结构:
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
And here is the query:
这是查询:
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
Any insight would be greatly appreciated.
如有任何见解,我们将不胜感激。
3 个解决方案
#1
21
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
edit:
编辑:
It's not a big deal, but I hate repeating conditions so we could refactor like:
这没什么大不了的,但我讨厌重复的条件,所以我们可以重构:
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
This way, if you change your case condition, it's in one spot only.
这样,如果你改变你的情况,它只是在一个地方。
#2
4
Group different things separately, join groups.
将不同的东西分开分组,加入组。
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
Also, if only SQL keywords are caps and the rest is not, readability increases. IMHO.
而且,如果只有SQL关键字是大写的,其余的不是,可读性就会增强。恕我直言。
#3
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
#1
21
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
edit:
编辑:
It's not a big deal, but I hate repeating conditions so we could refactor like:
这没什么大不了的,但我讨厌重复的条件,所以我们可以重构:
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
This way, if you change your case condition, it's in one spot only.
这样,如果你改变你的情况,它只是在一个地方。
#2
4
Group different things separately, join groups.
将不同的东西分开分组,加入组。
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
Also, if only SQL keywords are caps and the rest is not, readability increases. IMHO.
而且,如果只有SQL关键字是大写的,其余的不是,可读性就会增强。恕我直言。
#3
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