繁体   English   中英

MYSQL左联接和内联接

[英]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可能意味着您得到了错误的计数:

  1. inner join employee on attendance.e_id_f = employee.e_id如果一天没有匹配的记录,则当天的attendance.e_id_f将为null。 内部联接将从结果集中消除该记录。 解决方案:也使此连接成为左连接。

  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联接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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM