SQL查询以查找具有部门名称的位置以及没有部门的位置

时间:2016-11-01 14:10:10

标签: sql oracle

我遇到了以下关于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);

enter image description here

但我只得到27行:

SELECT department_name, city  
FROM locations 
JOIN departments USING (location_id);

为什么OR不起作用?谢谢!

修改

正如@mathguy指出的那样,我在NULL表的location_id列中有一个departments部门。这就是为什么NOT IN不返回任何行。否则,我会有更多的行在departments表中查找位置ID。

4 个答案:

答案 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 joinunion条款。