2016-10-16 45 views
1

我試圖通過將employees表與attendance_chart表加入attendance_status列中以獲得所有員工缺席和當前天數的總計數左加入表兩次以獲得單獨記錄

SELECT 
    e.id AS employee_id, 
    COUNT(present_days_chart.id) as present_days_count, 
    COUNT(absent_days_chart.id) as absent_days_count 

FROM 
    employees e 
    LEFT JOIN attendance_chart present_days_chart ON e.id = present_days_chart.attendance_for_employee_id AND present_days_chart.attendance_status = 'present' 
    LEFT JOIN attendance_chart absent_days_chart ON e.id = absent_days_chart.attendance_for_employee_id AND absent_days_chart.attendance_status = 'absent' 

WHERE 
    e.id IN (106,138) 

GROUP BY 
    e.id 

但是,查詢返回保持我相同數量的在present_days_count記錄和absent_days_count列的每一行。

我在做什麼錯?

+2

rbr94的回答是正確的。我只想補充一點,如果你想知道爲什麼,試着選擇*來看看你實際計算的數目(左連接將添加所有必要的行,從原表中複製行) –

+2

原因是:使用兩個LEFT JOIN在同一張桌子上,你創建了一個像CROSS JOIN的東西。結果是現在和不在的日子的產物。只有沒有在場或不在場的員工纔會得到正確的結果。 –

回答

4

嘗試使用CASE WHENSUM

SELECT e.id, 
     SUM(CASE WHEN days_chart.attendance_status = 'present' THEN 1 ELSE 0 END) AS present_days_count , 
     SUM(CASE WHEN days_chart.attendance_status = 'absent' THEN 1 ELSE 0 END) AS absent_days_count 

FROM employees e 
LEFT JOIN attendance_chart days_chart ON e.id = days_chart.attendance_for_employee_id 
WHERE e.id in (106,138) 
GROUP BY e.id 

有了這個SUM + CASE WHEN結構應該指望每一個具有特定的attendance_status,並最終與SUM幫助總結了所有罪名記錄和GROUP BY

+0

您的WHERE條件會將LEFT JOIN轉換爲INNER JOIN。更好地使用'e.id'就像在原始查詢中一樣。 –

+0

@PaulSpiegel是的,你是對的我糾正這一點 – rbr94

0

你有沒有嘗試重寫它有點不同?

SELECT 
    e.id AS employee_id, 
    COUNT(present_days_chart.id) as present_days_count, 
    COUNT(absent_days_chart.id) as absent_days_count 

FROM 
    employees e 
    LEFT JOIN (SELECT * FROM attendance_chart WHERE attendance_status = 'present') AS present_days_chart ON e.id = present_days_chart.attendance_for_employee_id 
    LEFT JOIN (SELECT * FROM attendance_chart WHERE attendance_status = 'absent') AS absent_days_chart ON e.id = absent_days_chart.attendance_for_employee_id 

WHERE 
    e.id IN (106,138) 

GROUP BY 
    e.id 
+0

沒有。試過了,仍然返回相同的行。 –