我的LEFT JOIN没有返回正确的结果。我究竟做错了什么?

时间:2014-03-17 13:48:17

标签: sql sql-server join

当我在两个表之间以INNER JOIN运行查询时,我得到了正确的结果 - 总共182个。

但是,当我以LEFT JOIN运行查询时,我只返回8条记录。我是否错误地执行了连接?

首先是代码:

select e.username,
       e.password,
       coalesce(r.access_level, 0) as orgid 
  from employees e 
       left join retired r 
           on e.employeeid = r.employeeid 
 where access_level=3

Retired表只有182条记录。这两个表都与EmployeeId相关联。

Retired表中的82条记录也存在于Employees中,但Employees表中有超过7千条记录。

其中一个字段名Retired名为Access_Level,值为3.

为什么LEFT JOIN没有给我一个准确的结果?

3 个答案:

答案 0 :(得分:2)

在WHERE子句中使用退役表中的字段基本上是自动执行INNER JOIN,因为只返回具有有效access_level值(即NOT NULL)的记录。

如果要查看员工的所有记录,则需要修改WHERE子句以考虑退休时没有匹配的员工记录,例如说WHERE r.access_level = 3 OR r.employeeid IS NULL

答案 1 :(得分:2)

如果Access_LevelRetired表中的列,那么对于员工中没有退休相应行的任何行,其值将为NULL。然后,这些行将被WHERE子句过滤掉,因为它们Access_Level为3.将该条件移动到ON子句就足够了:

select e.username,
       e.password,
       coalesce(r.access_level, 0) as orgid 
  from employees e 
       left join retired r 
           on e.employeeid = r.employeeid and access_level=3

答案 2 :(得分:1)

外连接和条件的技巧是将条件从where子句移动到join condtions子句中:

select
    e.username,
    e.password,
    coalesce(r.access_level, 0) as orgid 
from employees e 
left join retired r 
    on e.employeeid = r.employeeid 
    and access_level=3

你必须这样做的原因是where子句是行集上的过滤器,它在连接之后执行。通过在where子句中的外连接表上设置条件,可以有效地将外连接变为内部连接,因为错过的外连接在连接表的列中具有null值,但是where子句中的条件会坚持 那里的值。

join子句中的条件在连接时执行,因此通过将条件移出where子句,允许连接在仍然强加条件时错过 ,但如果在连接表中找不到合适的行,则返回一个全空连接行。


在评论中获得更多信息后,似乎这就是你想要的:

select distinct
    e.username,
    e.password,
    coalesce(r.access_level, 0) as orgid 
from employees e 
join retired r 
    on e.employeeid = r.employeeid 
    and access_level=3