2016-11-01 54 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條款。