2010-03-28 58 views
19

我的問題與Restricting a LEFT JOIN非常相似,有一個變化。從左外連接刪除重複

假設我有一個SHOP表和另一個表LOCATION。 Location是SHOP的子表,它有兩列感興趣的,一個是Division Key(稱爲KEY)和一個「SHOP」編號。這匹配SHOP表中的數字「NO」。

我想這個左外連接:

SELECT S.NO, L.KEY 
FROM SHOP S 
LEFT OUTER JOIN LOCATN L ON S.NO = L.SHOP 

,但我得到了很多重複的,因爲有一些屬於單店很多地方。我想消除它們,只是得到一個沒有重複的「商店,關鍵」條目列表。

的數據是正確的,但重複出現如下:

SHOP  KEY 
1  XXX 
1  XXX 
2  YYY 
3  ZZZ 
3  ZZZ etc. 

我想的數據出現像這個:

SHOP  KEY 
1  XXX 
2  YYY 
3  ZZZ etc. 

SHOP表:

NO 
1  
2  
3  

LOCATION表:

LOCATION SHOP KEY 
    L-1  1 XXX 
    L-2  1 XXX 
    L-3  2 YYY 
    L-4  3 YYY 
    L-5  3 YYY 

(Oracle 10g數據庫)

+0

儘管如此,您應該不會收到任何重複項目,但如您所述,如果您擁有一個以上的店鋪位置記錄,則可能會獲得多個關鍵店鋪。請解釋或舉例說明你的意思是「重複」。 – 2010-03-28 15:12:11

+1

@Marcus起初我也這麼認爲,但我假設多個位置可以有相同的分割鍵。 – 2010-03-28 15:14:12

+0

@馬庫斯與馬丁:啊,我不認爲我說得很清楚。是多個地點可以擁有相同的分區鍵。 (嚴格地說,divnkey是商店的父母,所以層次結構就像這個Divnkey> Shop> location)。我試圖用適當的分區密鑰數據填充Shop的表格。聽起來很奇怪,但這是一次性的過程,我試圖從表LOCATION的數據中爲表SHOP生成更新腳本 - 通過選擇'update shop set divnkey = ....'命令。不想複雜的問題,所以把簡單的選擇。 – 2010-03-28 16:06:12

回答

24

您需要GROUP BY「S.No」 &「L.KEY」

SELECT S.NO, L.KEY 
FROM SHOP S 
LEFT OUTER JOIN LOCATN L 
ON S.NO = L.SHOP 
GROUP BY S.NO, L.KEY 
+0

使用'GROUP BY',相當於Oracle上的'DISTINCT'http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:32961403234212但是在其他引擎上有時會更快,例如Postgres(使用散列而不是排序) – vladr 2010-03-28 23:45:54

+0

好吧,你只是讓我感到非常愚蠢。這工作完美。謝謝。 但是,當左外層應該處理這個問題時,爲什麼需要所有的group by。正如我在試圖理解左外層是如何工作的。 – 2010-03-29 04:17:00

+0

@Kaushik:左外連接不等於也不暗示GROUP BY或DISTINCT。 LEFT JOIN從左(第一個)表中取所有行,並在滿足連接條件的右(第二個)表中加入所有行。在left * outer * join中,如果在右表中沒有找到與左表中的數據匹配的數據,那麼對於所有右表數據,左表數據仍然返回NULL值。沒有任何分組是明示或暗示的。就我個人而言,我會使用DISTINCT,因爲我認爲它更清楚地指定了意圖,但是YMMV。 – 2010-03-29 12:22:35

7

編輯繼在您的方案更新

我想你應該可以用一個簡單的子查詢做到這一點(雖然我沒有測試過這對一個Oracle數據庫)。類似以下內容

UPDATE shop s 
SET divnkey = (SELECT DISTINCT L.KEY FROM LOCATN L WHERE S.NO = L.SHOP) 

上述情況會在商店與位於多個部門的位置關聯時引發錯誤。

如果你只是想忽略這種可能性,並選擇在該事件中的任意一個,你可以使用

UPDATE shop s 
SET divnkey = (SELECT MAX(L.KEY) FROM LOCATN L WHERE S.NO = L.SHOP) 
+0

尼斯:)這就是爲什麼獲得多個角度很重要。感謝Martin,你的解決方案絕對能夠滿足我的基本要求(但是另一個答案特別關注刪除重複項,因此必須標記該項)。乾杯 – 2010-03-29 04:19:39

6

我也有這個問題,但我不能使用GROUP BY修復它,因爲我也返回TEXT類型的字段。 (使用DISTINCT也一樣)。

此代碼給我重複:

select mx.*, case isnull(ty.ty_id,0) when 0 then 'N' else 'Y' end as inuse 
from master_x mx 
left outer join thing_y ty on mx.rpt_id = ty.rpt_id 

我通過如此重寫它固定它:

select mx.*, 
case when exists (select 1 from thing_y ty where mx.rpt_id = ty.rpt_id) then 'Y' else 'N' end as inuse 
from master_x mx 

正如你可以看到我不關心第二表中的數據(thing_y ),只是其中的rpt_id是否大於零匹配。 (僅供參考:rpt_id也不是第一張表的主鍵,master_x)。