2017-01-04 146 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

非常好,谢谢很多影子 –