2013-06-22 85 views
2

問題是還返回包含空值的行。下面是創建表並使用示例數據填充它的SQL代碼。完全外部自我加入

我期待下面,但查詢不顯示空值的兩行。

 
src_t1 id1_t1 id2_t1 val_t1  src_t2 id1_t2 id2_t2 val_t2 

             b  z  z  4 
a  w  w  100    b  w  w  1 
a  x  x  200    b  x  x  2 
a  y  y  300 

數據:

CREATE TABLE sample (
    src VARCHAR(6) 
    ,id1 VARCHAR(6) 
    ,id2 VARCHAR(6) 
    ,val FLOAT 
); 

INSERT INTO sample (src, id1, id2, val) 
VALUES ('a', 'w', 'w', 100) 
     ,('b', 'w', 'w', 1) 
     ,('a', 'x', 'x', 200) 
     ,('b', 'x', 'x', 2) 
     ,('a', 'y', 'y', 300) 
     ,('b', 'z', 'z', 4) 
; 

這是我的測試查詢。當t1.src ='a'和t1.id1 ='y'或者當t2.src ='b'和t2.id1 ='z'時,它不顯示結果。

爲什麼?

什麼是正確的查詢?

SELECT t1.src, t1.id1, t1.id2, t1.val 
    ,t2.src as src2, t2.id1, t2.id2, t2.val 
FROM sample t1 FULL OUTER JOIN sample t2 
    ON t1.id1 = t2.id1 AND t1.id2 = t2.id2 
WHERE (t1.src = 'a' AND t2.src = 'b') 
    OR (t1.src IS NULL AND t1.id1 IS NULL AND t1.id2 IS NULL) 
    OR (t2.src IS NULL AND t2.id1 IS NULL AND t2.id2 IS NULL) 

我也試過WHERE子句中移動的條件爲ON條款也是如此。

TIA。

+0

從我的答案適應SQL中的其他問題,在這裏它看起來像'從(SELECT * FROM樣本其中src ='a')t1完整外連接(select * from sample where src ='b')t2 on t2.id1 = t1.id1 and t2.id2 = t1.id2':http://www.sqlfiddle。 com /#!6/e7b1e/3 – hvd

+0

@hvd謝謝。這樣可行。如此簡單,當你知道如何。 – Karl

+0

@ hvd如果您將它作爲答案發布,我會很樂意接受它。 – Karl

回答

2

WHERE子句的評估太晚了,有效地將您的查詢轉換爲內部聯接。

SELECT t1.src, t1.id1, t1.id2, t1.val 
    ,t2.src as src2, t2.id1, t2.id2, t2.val 
FROM (
    select * from sample 
    where src='a' 
) t1 FULL OUTER JOIN (
    select * from sample 
    where src='b' 
) t2 
    ON t1.id1 = t2.id1 AND t1.id2 = t2.id2 

產生這樣的結果集:

src id1 id2 val   src2 id1 id2 val 
---- ---- ---- ----------- ---- ---- ---- ----------- 
a w w 100   b w w 1 
a x x 200   b x x 2 
NULL NULL NULL NULL  b z z 4 
a y y 300   NULL NULL NULL NULL 

更新
還要注意使用兩個子查詢的

相反,使用適當的JOIN語法編寫這樣的查詢清楚地將源表分成兩個不同的relvars。我第一次提交時錯過了一分鐘。

+0

-1因爲問題明確包含預期的輸出,這與您的輸出不同。 – hvd

+0

@ hvd是正確的。彼得,請注意您的結果在兩個來源列中如何包含'a'和'b'值。重點是一方只有'a',另一方只有'b'。 – Karl

+0

@Karl:已更正 –

1

其實,我認爲解決的辦法是有點清潔,如果一個CTE使用:

WITH A AS (
    select * from sample where src='a' 
), 
B AS (
    select * from sample where src='b' 
) 
SELECT * 
FROM A FULL OUTER JOIN B 
    ON A.ID1 = B.ID1 AND A.ID2 = B.ID2 
;