连接查询的原因不明/奇怪的行为

时间:2014-05-29 08:59:15

标签: sql join oracle11g oracle-sqldeveloper

select d.department_id "Department Nummber", department_name,
       nvl(last_name, 'NoManager!') "Manager",
       job_id

from departments d left outer join employees e on (d.manager_id=e.employee_id)
     natural join jobs j

order by 1;

我无法弄清楚上述查询的结果,执行时会返回11行。谜一点是,当从选择列表中删除“job_id”时,同一个查询返回513行,或者整个列表被替换为count(*),其中返回的行数也是513.

我认为这是导致无法解释的结果的自然联接,如替换

  

自然联接职位

  

使用(job_id)

加入作业

总是按预期产生11行,并“解决”问题。

我正在使用SQLDeveloper和Oracle Database 11g。我很感激有关这是怎么回事。

谢谢。

2 个答案:

答案 0 :(得分:0)

我假设工作表与员工的工作表相关联。

Natural join就像一个inner join,因此您的left join允许您显示"没有经理"结果(也许还有其他内容)但是natural/inner join您正在将left join转换为inner join,因此删除所有未加入的左连接+没有工作的员工

您可以在作业上使用left joinnatural left join

答案 1 :(得分:0)

我永远不会使用自然联接 - 你发现的太容易出错(现在以一种我以前没有意识到的新方式!)

这里的问题是,您的查询中的自然联接在EMPLOYEES和JOBS之间,但在结果之间

(select d.department_id "Department Nummber", department_name,
       nvl(last_name, 'NoManager!') "Manager",
       job_id
from departments d left outer join employees e on (d.manager_id=e.employee_id))

和JOBS。在这种情况下,有一个要连接的列:JOB_ID。

但是当您从SELECT中删除JOB_ID时,您现在正在加入两个"表"没有公共列(第一个"表"是自然连接之前的select语句)。而自然连接的一些反直觉(但完全"逻辑")行为是,如果没有公共列,那么它执行笛卡尔积!看到这个简单的例子:

SQL> select * from dept;

    DEPTNO
----------
        10
        20
        30

SQL> select * from jobs;

    JOB_ID
----------
      1000
      2000
      3000

SQL> select deptno, job_id from dept natural join jobs;

    DEPTNO     JOB_ID
---------- ----------
        10       1000
        10       2000
        10       3000
        20       1000
        20       2000
        20       3000
        30       1000
        30       2000
        30       3000

9 rows selected.

为了获得您期望的行为,我认为您需要使用括号来获取适当的连接 - 例如:

select d.department_id "Department Nummber", department_name,
       nvl(last_name, 'NoManager!') "Manager",
       job_id
from departments d left outer join 
(select * from employees e natural join jobs j) x
on d.manager_id=x.employee_id
order by 1;

或者更好:永远,永远在结果重要的查询中使用自然联接!