2016-11-01 49 views
0

我碰到下面的SQL问题,他们的著名HR架构与部门名称的位置以及位置所附带的Oracle: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指出的那样,我在departments表中的列location_id曾与NULL部门。这就是为什么NOT IN不返回任何行。否则,我会有更多的行查找departments表中的位置标识。

+0

可能是坏的查询是第一个,而不是第二..左外连接应该使用ON,而不是使用 – Massimo

+0

@Massimo,为什么?它确实产生了期望的结果。 –

+0

http://docs.oracle.com/database/121/SQLRF/statements_10002.htm#i2107296 – Massimo

回答

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个城市没有设在那里的部门。

注意:如果location_id列中有NULL的部门,NOT IN条件将不起作用。如果可能的话,条件可以更改为not in (select location_id from departments where location_id is not null)

+0

嗯,'选择城市,从location_id不在的位置选择NULL(从部门选择location_id);'返回0行。 –

+0

它必须是同一个问题:您必须为location_id具有NULL的部门。这(我的意思是你的副本)不是标准的HR模式。 – mathguy

+0

是的。我做。非常感谢! –

0

使用相关子查询:

SELECT l.*, 
     (SELECT d.department_name 
     FROM departments d 
     WHERE d.location_id = l.location_id 
     ) as department_name 
FROM locations l; 

如果对多个部门中的位置的关注,那么就聚集在一起:

SELECT l.*, 
     (SELECT LISTAGG(d.department_name, ', ') WITHIN GROUP (ORDER BY d.department_name) as department_names 
     FROM departments d 
     WHERE d.location_id = l.location_id 
     ) as department_name 
FROM locations l; 
+1

这不起作用,因为位置中可能有多个部门因此从子查询返回多行。 –

+0

@MartinDimitrov一个连接也将返回多行?这向您展示了如何在没有OUTER JOIN的情况下编写查询,我已经解释了为什么OR在我的答案中不起作用。我不相信他们正在寻找你使用隐式语法。 –

+0

你试过了吗?它返回'ORA-01427:单行子查询返回多行' –

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) 
+0

即使看起来相当复杂,它也能正常工作。谢谢。 –

0

那么,如果你尝试很简单想象一些中间步骤:

让imagane交叉连接表并过滤之后呃你的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);。这种情况不会影响表格之间的交叉连接。
正因为如此,你应该得到额外的行没有部门loction。

这就是为什么你需要left joinunion条款。