2つの集計関数の値に基づいてテーブルからレコードをプルするSQLクエリの作成に取り組んでいます。これらの集約関数は、同じテーブルからデータを引き出しますが、フィルター条件は異なります。私が遭遇する問題は、SUMの結果が、SUM関数を1つだけ含める場合よりもはるかに大きいことです。一時テーブルを使用してこのクエリを作成できることはわかっていますが、単一のクエリのみを必要とするエレガントなソリューションがあるかどうか疑問に思っています。
この問題を説明するために簡略化したバージョンを作成しました。テーブルの構造は次のとおりです。
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
どんな洞察もいただければ幸いです。
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つのスポットのみにあります。
さまざまなものを別々にグループ化し、グループに参加します。
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キーワードのみが大文字で残りが大文字でない場合、読みやすさが向上します。私見では。
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