带有空值的SQL自连接问题

时间:2011-02-02 03:00:12

标签: sql join

让我们看一下Employee表的经典自联接示例,其中我们有列empId,managerId,empName,Managername。我试图查看每个作为经理的员工,然后使用表名中的其他名称加入经理姓名。现在我遇到问题的部分是某些记录的经理ID可以为null。在这些情况下,sql不起作用,因为对于mgrId为null的行,mgr.name为null:

SELECT emp.Name, mgr.Name FROM Employee e
LEFT JOIN Employee mgr ON e.empId=mgr.mgrId 
JOIN Name nm ON nm.name = mgr.Name

有人可以为此提供解决方案吗?

很抱歉过于简单化了问题: 它更像是每个员工行,我也想要mgr行(mgrId为empId的行),然后将mgr行的属性加入到其他表中。像这样:

select 
   emp.empId,mgr.empId,dept.deptName 
from Employee emp  
JOIN Address addr on 
   emp.houseNo = addr.houseNo  
JOIN dept dept on 
   dept.deptAddress = addr.deptAddress  
LEFT JOIN Employee mgr on 
   emp.empId = mgr.empId  
JOIN Address address on 
   mgr.houseNo = address.houseNo  
JOIN dept department on 
   department.houseNo=address.deptAddress  
where 
   department.deptId=dept.deptId  

使用所有左连接对此无效。谢谢你的帮助。

3 个答案:

答案 0 :(得分:8)

一旦引入了左连接,您通常也希望使用LEFT跟随所有后续连接。链中的单个INNER JOIN也会将所有内容减少到INNER JOIN之前。

SELECT 
    emp.Name, mgr.Name 
FROM Employee e
LEFT JOIN Employee mgr ON 
    e.empId = mgr.mgrId 
LEFT JOIN Name nm ON 
    nm.name = mgr.Name

答案 1 :(得分:2)

首先,你没有加入后缀吗?不应该

         ON e.empId = mgr.mgrId 

         ON e.mgrId = mgr.empId

即使你工作,名为“mgr”的表也应该保存mgr.empId和mgr.name的记录,这样就可以了。

其次,我不喜欢加入Name部分。您应该将其转换为ID。 (有人结婚了,接下来你知道你有一堆孤儿......)我怀疑这张桌子不是真的需要。

第三,结果集中的2列具有相同的名称(Name)这一事实可能会导致以后出现问题 - 如果没有别的话就会出现不好的做法。

这是我将使用的SQL:

SELECT emp.Name, '(none)' AS Manager 
FROM Employee emp
WHERE NOT EXISTS (SELECT 1
    FROM Employee mgr 
    WHERE mgr.empId = emp.mgrId)

UNION ALL

SELECT emp.Name, mgr.Name AS Manager 
FROM Employee emp
JOIN Employee mgr ON emp.mgrId=mgr.empId 
JOIN Name nm ON nm.name = mgr.Name
ORDER BY 1, 2

如果这看起来效率低下,请不要担心,现代SQL编译器在大多数情况下都会以同样的方式结束,无论你如何编写它。

但首先,我会运行此SQL以查看我是否有任何员工在Name表中没有记录并修复它们:

SELECT *
FROM Employee e
LEFT JOIN Name nm 
ON nm.name = e.Name
WHERE nm.name is null

答案 2 :(得分:0)

将ON子句移动到更合适的位置

SELECT emp.Name, mgr.Name
FROM Employee e
    LEFT JOIN Employee mgr 
         JOIN Name nm
         ON nm.name = mgr.Name
    ON e.empId=mgr.mgrId