[英]MYSQL left join and inner join
我有3张桌子
员工=> e_id(PK),dep_id(Fk)
部门=> d_id(PK)
出勤=> id(PK),缺席日期(DATE),e_id_f(FK)
我想获得某个时期某部门缺勤的员工人数。
我创建了一个名为MyDates的表
CREATE TABLE MyDates (mydate date);
和此过程用日期填充MyDates表
CREATE PROCEDURE filldates(dateStart DATE, dateEnd DATE)
开始
WHILE dateStart <= dateEnd DO
INSERT INTO MyDates (mydate) VALUES (dateStart);
SET dateStart = date_add(dateStart, INTERVAL 1 DAY);
END WHILE;
END;
然后我调用了用日期CALL filldates('2017-01-01','2017-03-31')填充MyDates的过程;
然后我做了这个选择语句:
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 的屏幕截图
我可以看到您的查询有3个问题。 1st 2会导致删除找不到匹配记录的日期,而3rd可能意味着您得到了错误的计数:
inner join employee on attendance.e_id_f = employee.e_id
如果一天没有匹配的记录,则当天的attendance.e_id_f
将为null。 内部联接将从结果集中消除该记录。 解决方案:也使此连接成为左连接。
AND employee.dep_id = 4
这只会将记录中包含与之相关的员工记录的记录保留在结果集中,因此如果您的缺勤日为0,则此条件会将其从结果集中删除。 解决方案:在连接条件中包括此条件。
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
联接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
可确保仅返回属于dep_id = 4
那些出勤记录,然后将这些记录保留在您的日期表中。 在这种情况下,无需更改您要计数的字段。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.