有兩張表單 表X、表Y (裡面有A、B、C三欄位)
根據A、B、C三欄位 我想取表X有但是不存在於表Y的資料
因為需要結合多欄位(A、B、C三欄位)來判斷 所以原本都是用CONCAT來結合字串
--- 原本的寫法
SELECT * FROM 表X x
WHERE CONCAT(x.A,x.B,x.C)
NOT IN (SELECT CONCAT(y.A,y.B,y.C) FROM 表Y y)
但效率很差 想以LFET JOIN方式改寫
可是多條件方式我查不出來
--- 後來改寫 但結果不是我要的...
SELECT * FROM 表X x
LEFT JOIN 表Y y ON
x.A=y.A AND x.B=y.B AND x.C=y.C
AND y.A IS NULL AND y.B IS NULL AND y.C IS NULL;
參考資料如下
--- 表X
A B C
甲 1 001
乙 2 001
丙 3 001
丁 4 001
己 5 001
--- 表Y
A B C
甲 1 002
乙 2 001
丙 3 001
丁 4 002
戊 5 001
--- 想要的結果
A B C
甲 1 001
丁 4 001
己 5 001
再請各位指教
謝謝 !
SELECT X.*
FROM X
LEFT JOIN Y ON
X.A=Y.A AND X.B=Y.B AND X.C=Y.C
WHERE 1=1
AND Y.A IS NULL AND Y.B IS NULL AND Y.C IS NULL;
發問的SQL語法寫錯了...
AND y.A IS NULL AND y.B IS NULL AND y.C IS NULL;
實際是這樣=>WHERE y.A IS NULL AND y.B IS NULL AND y.C IS NULL;
發現你的寫法跟我的一樣 可是DEMO裡面跑得出來... 我的不行
進一步發現可能是受其他欄位的影響@@
其實我還有一欄是日期 A B C三欄在不同日期會有重複 應該是這樣造成我結果跑不出來
--- 原本LEFT JOIN寫法的完整樣貌 (結果不是我要的)
SELECT * FROM 表X x
LEFT JOIN 表Y y ON
x.A=y.A AND x.B=y.B AND x.C=y.C
WHERE x.CREATEDATE='2019-12-24' AND y.FinishDate='2019-12-24' AND y.A IS NULL AND y.B IS NULL AND y.C IS NULL;
--- 重新改寫 結果成功了!
SELECT * FROM 表X x
LEFT JOIN (SELECT * FROM 表Y temp_y WHERE temp_y.FinishDate='2019-12-24') y ON
x.A=y.A AND x.B=y.B AND x.C=y.C
WHERE x.CREATEDATE='2019-12-24' AND y.A IS NULL AND y.B IS NULL AND y.C IS NULL;
如果是使用OUTER JOIN
又想要判斷哪些資料不存在(IS NULL
)請把判斷寫在Where
上
或者你可以使用NOT EXISTS
SELECT *
FROM X
WHERE NOT EXISTS (
SELECT 1
FROM Y
WHERE X.A=Y.A AND X.B=Y.B AND X.C=Y.C
)
SELECT x.* FROM 表X x
LEFT JOIN 表Y y ON
x.A=y.A AND x.B=y.B AND x.C=y.C
WHERE y.A IS NULL OR y.B IS NULL OR y.C IS NULL;
你要的是不是OR ?
還有最前面只取X表的就好(建議是把欄位都列出來)
我向來比較懶,不想寫那麼長的 sql 指令。
我會在 表X 和 表Y 裡,各添加一個虛擬欄位 d ,其值為 CONCAT(A,B,C),並加上索引。
這時,查詢指令就很簡單啦。
--- 原本的寫法
SELECT * FROM 表X x
WHERE d NOT IN (SELECT d FROM 表Y y)