次のシナリオのクエリを理解するために、実際にいくつかの助けを借りることができます。
tblStaff
| ESID | EID | FName | LName |
+------+-----+-------+--------+
| 1 | 10 | Joe | Smith |
| 2 | 10 | Dan | Jones |
| 3 | 10 | Rick | Brown |
| 4 | 10 | Pete | Miller |
| 5 | 10 | Ken | White |
tblStaffTime
| TCID | EID | ESID | DTIn | DTOut |
+------+-----+------+-------------------------+-------------------------+
| 1 | 10 | 1 | 2013-09-22 08:00:00.000 | 2013-09-22 17:00:00.000 |
| 2 | 10 | 1 | 2013-09-23 08:00:00.000 | NULL |
| 3 | 10 | 2 | 2013-09-23 08:00:00.000 | 2013-09-23 17:00:00.000 |
| 4 | 10 | 3 | 2013-09-22 08:00:00.000 | 2013-09-22 17:00:00.000 |
| 5 | 10 | 3 | 2013-09-23 08:00:00.000 | NULL |
私の目的は次のとおりです。 EID が 10 で、最新の DTOut が null でないか、この EID の tblStaffTime にレコードがまったくないすべての人をリストします。つまり、EID が 10 のすべてのスタッフについて、出勤する準備ができている人のリストです。
これまでの私のSQL:
SELECT tblStaff.ESID AS ID,tblStaff.SFirst + CHAR(32) + tblStaff.SLast AS StaffName
FROM tblStaff
LEFT JOIN tblStaffTime ON tblStaff.ESID = tblStaffTime.ESID
WHERE tblStaff.ESID = (SELECT ESID FROM tblStaffTime WHERE EID = '10' AND ESID = tblStaffTime.ESID AND DTIn IS NOT NULL AND DTOut IS NOT NULL)
UNION ALL
SELECT tblStaff.ESID AS ID,tblStaff.SFirst + CHAR(32) + tblStaff.SLast AS StaffName
FROM tblStaff
LEFT JOIN tblStaffTime ON tblStaff.ESID = tblStaffTime.ESID
WHERE NOT EXISTS (SELECT 1 FROM tblStaffTime WHERE tblStaffTime.ESID = tblStaff.ESID) AND tblStaff.EID = '10'
ORDER BY tblStaff.SFirst + CHAR(32) + tblStaff.SLast
望ましい出力:
| ESID | StaffName |
+------+-------------+
| 2 | Dan Jones |
| 5 | Ken White |
| 4 | Pete Miller |
私のユニオンの南は、この EID に出勤していないスタッフを取得するという私の問題を解決します。私の主な問題は、組合の北部です。最新の DTIn を取得し、そのレコードの DTOut が null であるかどうかを確認して、記録の準備ができているかどうかを判断する必要があります。この SQL はすべて、よりきれいに記述できると確信しています。今は専門家に任せます。