2009-09-16 47 views
1

如何在使用左外連接時排除一組值?排除來自左外連接的集合

考慮下面的查詢:

SELECT i.id, 
     i.location, 
     area.description 
    FROM incident_vw i, 
     area_vw area 
WHERE i.area_code = area.code(+) 
    AND i.area_code NOT IN ('T20', 'V20B', 'V20O', 'V20P') 

查詢執行,但沒有無效區域代碼值出現的。

BE AWAREINCIDENT_VW.area_code can和does有NULL值。

有關如何在不使用PL/SQL的情況下匹配NULL事件區碼而排除給定的一組區碼的任何想法?

ANSI更新

使用等效ANSI SQL也不起作用:

SELECT i.id, 
      i.location, 
      area.description 
     FROM incident_vw i 
LEFT JOIN area_vw area 
     ON area.code = i.area_code 
    WHERE i.area_code NOT IN ('T20', 'V20B', 'V20O', 'V20P') 

解決方案

這工作:

SELECT i.id, 
     i.location, 
     area.description 
    FROM incident_vw i, 
     area_vw area 
WHERE i.area_code = area.code(+) 
    AND (i.area_code NOT IN ('T20', 'V20B', 'V20O', 'V20P') and i.area_code IS NULL) 

感謝大家!

+0

@戴夫:停止使用'WHERE 1 = 1' - 1 = 1什麼都不做,得到優化。 – 2009-09-16 18:24:19

+1

@Dave:請確認'INCIDENT_VW.area_code'是否可以有NULL值。 – 2009-09-16 18:27:25

+0

@Dave:1)鏈接是針對SQL Server的,而不是Oracle 2)鏈接說明了我所做的 - 1 = 1什麼都不做。 – 2009-09-16 18:28:27

回答

4

似乎問題是IN正在刪除所有NULL爲空的area_codes。

這給一試:

SELECT i.id, 
      i.location, 
      area.description 
     FROM incident_vw i 
LEFT JOIN area_vw area 
     ON area.code = i.area_code 
    WHERE (i.area_code NOT IN ('T20', 'V20B', 'V20O', 'V20P') 
      OR i.area_code IS NULL) 

應該給予期望的結果...

+0

謝謝!我不得不將(+)換成area.code。 – 2009-09-16 19:04:00

0

我想我會嘗試這個辦法:

SELECT i.id, 
     i.location, 
     area.description 
    FROM (SELECT * 
      FROM incident_vw 
     WHERE i.area_code NOT IN ('T20', 'V20B', 'V20O', 'V20P') 
      OR i.area_code IS NULL) i 
    , area_vw area 
WHERE i.area_code = area.code (+) 

或者ANSI等效:

SELECT i.id, 
      i.location, 
      area.description 
    FROM (SELECT * 
      FROM incident_vw 
      WHERE i.area_code NOT IN ('T20', 'V20B', 'V20O', 'V20P') 
       OR i.area_code IS NULL) i 
LEFT JOIN area_vw area 
     ON i.area_code = area.code 
0

我不是100%當然,也許你正在加入area.code 上的l.area_code,你應該加入l.area.code的area_code。

SELECT i.id, 
     i.location, 
     area.description 
    FROM incident_vw i, 
     area_vw area 
WHERE 1=1 
    AND i.area_code = area.code(+) 
    AND i.area_code NOT IN ('T20', 'V20B', 'V20O', 'V20P') 

應該是:

SELECT i.id, 
     i.location, 
     area.description 
    FROM incident_vw i, 
     area_vw area 
WHERE 1=1 
    AND i.area_code(+) = area.code 
    AND i.area_code NOT IN ('T20', 'V20B', 'V20O', 'V20P') 
+0

從問什麼,我會假設相同。 – Sivvy 2009-09-16 18:34:19

+0

不幸的是,沒有。 – 2009-09-16 18:51:11

+0

(+)在左連接中將丟失行的字段中,在這種情況下爲area.code。這個例子的原始版本是正確的。 – 2009-09-16 19:03:19

0

你能嘗試:

SELECT i.id, 
      i.location, 
      area.description 
     FROM incident_vw i 
LEFT JOIN area_vw area 
     ON area.code = i.area_code 
    WHERE NVL(i.area_code,'something') NOT IN ('T20', 'V20B', 'V20O', 'V20P') 
+0

由於空值檢查與要排除的值進行比較沒有意義。 – 2009-09-16 18:34:09

0
SELECT i.id, 
     i.location, 
     area.description 
    FROM incident_vw i 
    LEFT JOIN area_vw area 
    ON i.area_code = area.code 
    WHERE i.area_code NOT IN ('T20', 'V20B', 'V20O', 'V20P') 
UNION 
SELECT i.id, 
     i.location, 
     NULL as description 
    FROM incident_vw i 
    WHERE i.area_code IS NULL 
+0

從我對該問題的理解中,想要在結果集中包含所有的i.area_code = NULL記錄。工會會這樣做。 – hgmnz 2009-09-16 18:45:06

0

的語法看起來是正確的。你應該測試你的數據,以確保你的理智。試試這個:

SELECT count(*) 
FROM incident_vw i 
WHERE i.area_code NOT IN 
     (SELECT a.area_code 
     FROM area_vw a); 

這會告訴你,如果你有任何沒有區域表中的區域表示的事件。

+0

恰好有一起沒有區號的事件。 – 2009-09-16 18:53:57

0

我不知道我理解的問題,但如果你想更希望得到空值在排除列表中的區號,然後只要將你的病情從哪裏來的JOIN條件:

SELECT i.id, 
      i.location, 
      area.description 
     FROM incident_vw i 
LEFT JOIN area_vw area 
     ON area.code = i.area_code 
     AND area.code NOT IN ('T20', 'V20B', 'V20O', 'V20P')