MYSQL离开了连接和内连接

时间:2017-01-04 17:21:26

标签: mysql left-join inner-join

我有3张桌子

员工=> e_id(P.K),dep_id(F.k)

部门=> d_id(P.K)

出勤=> id(P.K),date_of_absence(日期),e_id_f(F.K)

我希望在一段时间内获得某个部门缺席员工的数量。

我创建了一个名为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填写日期(&#39; 2017-01-01&#39;,&#39; 2017-03-31&#39;);

然后我做了这个选择声明:

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

1 个答案:

答案 0 :(得分:0)

我可以看到您的查询有3个问题。第一个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)

  4. 修改后的查询:

    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的那些出勤记录,然后将这些记录保留在日期表中。在这种情况下,无需更改您正在计算的字段。