我遇到了以下关于Oracle附带的着名HR
架构的SQL问题:
编写SQL查询以查找每个位置的所有位置和部门以及没有部门的位置。不要使用OUTER JOIN。
使用OUTER JOIN
很容易:
SELECT department_name, city
FROM locations
LEFT OUTER JOIN departments USING (location_id);
我得到43个结果。我试过这个:
SELECT department_name, city
FROM locations l, departments d
WHERE l.location_id = d.location_id OR
l.location_id NOT IN (SELECT DISTINCT location_id FROM departments);
但我只得到27行:
SELECT department_name, city
FROM locations
JOIN departments USING (location_id);
为什么OR
不起作用?谢谢!
修改
正如@mathguy指出的那样,我在NULL
表的location_id
列中有一个departments
部门。这就是为什么NOT IN
不返回任何行。否则,我会有更多的行在departments
表中查找位置ID。
答案 0 :(得分:2)
select l.city, d.department_name from locations l, departments d
where l.location_id=d.location_id
UNION
select l2.city, null department_name
from locations l2
where not exists (select 1 from depertments d2 where d2.location_id=l2.location_id)
答案 1 :(得分:2)
从内部联接获取city, department_name
,然后union all
,如下:
select city, department_name
from <inner join>
union all
select city, NULL
from locations
where location_id not in (select location_id from departments);
union all
的第二个分支将为您提供16个没有部门的城市。
注意:如果NOT IN
列中有NULL
的部门,location_id
条件将无效。如果可能,则可以将条件更改为not in (select location_id from departments where location_id is not null)
。
答案 2 :(得分:0)
使用相关子查询:
fieldErrors
如果某个地点的多个部门存在问题,那么只需将它们汇总在一起:
SELECT l.*,
(SELECT d.department_name
FROM departments d
WHERE d.location_id = l.location_id
) as department_name
FROM locations l;
答案 3 :(得分:0)
如果你试图想象一些中间步骤,这很简单:
允许表格的想象交叉连接,并在使用where子句过滤结果之后。在该行集中,不会显示任何具有非空位置和空部门的行。您可以使用下一个查询证明它:
SELECT department_name, city
FROM locations l, departments d
WHERE d.location_id is null;
no row selected
但您指定l.location_id NOT IN (SELECT DISTINCT location_id FROM departments);
。这种情况不会影响表之间的交叉连接
因此,你应该在没有部门的情况下获得额外的行位置。
这就是为什么你需要left join
或union
条款。