2017-01-04 186 views
0

我有3個表MySQL的左連接和內連接

僱員=> E_ID(PK),dep_id(FK)

部=> D_ID(PK)

考勤=> ID(PK ),date_of_absence(DATE),e_id_f(FK)

我想知道特定部門的缺席員工人數。

我創建一個名爲MyDates

CREATE TABLE MyDates (mydate date); 

表和此過程,以填補與日期MyDates表

CREATE PROCEDURE filldates(dateStart DATE, dateEnd DATE) 

BEGIN

WHILE dateStart <= dateEnd DO 
    INSERT INTO MyDates (mydate) VALUES (dateStart); 
    SET dateStart = date_add(dateStart, INTERVAL 1 DAY); 
    END WHILE; 
END; 

然後我調用的過程來填充MyDates與日期CALL filldates('2017-01-01','2017-03-31');

然後我做了這個選擇語句:

select mydates.mydate, count(attendance.date_of_absence) 
from mydates left join attendance on 
mydates.mydate = attendance.date_of_absence 
where mydates.mydate Between "2017-01-01" AND "2017-01-31" 
group by mydates.mydate 

這個查詢得到我所需要的,但所有的部門,但對於某個部門的行數不正確,

select mydates.mydate, count(attendance.date_of_absence) 
from mydates 
left join attendance on mydates.mydate = attendance.date_of_absence 
inner join employee on attendance.e_id_f = employee.e_id 
where mydates.mydate Between "2017-01-01" AND "2017-01-31" AND employee.dep_id = 4 
group by mydates.mydate; 

這是一張截圖 IMG

+0

你可以添加你需要的數據和你以樣本形式得到的結果集。 – meet

+0

當然,請看看上面添加的截圖。 –

回答

0

您的查詢有3個問題,我可以看到。 1日2個結果摔落在沒有匹配記錄中找到的日期,第三個可能意味着你得到錯誤計數:

  1. inner join employee on attendance.e_id_f = employee.e_id - 如果沒有匹配的記錄了一天,然後attendance.e_id_f將是無效的那天。內部聯接將從結果集中消除此記錄。解決方案:將此連接也留下。

  2. AND employee.dep_id = 4 - 這隻會將結果集中的記錄保留在與結果集相關聯的記錄中,因此如果您有一天的缺勤時間爲0,則此條件將從結果集中消除該記錄。解決方案:在連接條件中包含此條件。

  3. count(attendance.date_of_absence) - 計數來自出席表的數據,在添加第二個左連接後將不正確。解決方案:改爲使用count(employee.dep_id)

修改後的查詢:

select mydates.mydate, count(employee.dep_id) 
from mydates 
left join attendance on mydates.mydate = attendance.date_of_absence 
left join employee on attendance.e_id_f = employee.e_id AND employee.dep_id = 4 
where mydates.mydate Between "2017-01-01" AND "2017-01-31" group by mydates.mydate 

替代解決方案是使用嵌套的聯接,在那裏你特別指示MySQL執行attendance inner join employee先加入。你仍然需要將employee.dep_id = 4條件移動到連接條件:

select mydates.mydate, count(attendance.date_of_absence) 
from mydates 
left join (attendance inner join employee) 
    on mydates.mydate = attendance.date_of_absence 
     and attendance.e_id_f = employee.e_id 
     and employee.dep_id = 4 
where mydates.mydate Between "2017-01-01" AND "2017-01-31" 
group by mydates.mydate 

在後一種情況下,嵌套的內部聯接確保只有那些出勤記錄返回屬於dep_id = 4,然後將這些記錄都加入到您的日期表。在這種情況下,不需要改變你正在計數的字段。

+0

非常好,謝謝很多影子 –