嘿嘿~~~SQL真的是一個很神奇的東西

[SQL] 當使用NOT IN碰到NULL會發生神馬事呢..

↑如這個圖,SQL這樣下是可以撈得出資料的,但先記一下omb04這個欄位值是NULL

 

[SQL] 當使用NOT IN碰到NULL會發生神馬事呢..

然後呢,當omb04增加 NOT IN的條件時,竟然就撈不出資料了[SQL] 當使用NOT IN碰到NULL會發生神馬事呢..

 

[SQL] 當使用NOT IN碰到NULL會發生神馬事呢..

再然後呢...,我改成用子查詢的寫法,又變得能撈出資料了[SQL] 當使用NOT IN碰到NULL會發生神馬事呢..

 

[SQL] 當使用NOT IN碰到NULL會發生神馬事呢..

還有一個很有趣的,調整exists子查詢寫法後,又撈不出資料了[SQL] 當使用NOT IN碰到NULL會發生神馬事呢..

.

.

.

問題是出在 NOT IN這個謂詞,只要是謂詞就會進行返還TRUE或FALSE的遊戲,但是NULL會返還TRUE還是FALSE呢?

omb04 NOT IN ('MISC-FREIGHT','MISC-M-DISCOUNT') 實際上就是AND Filter的語句,也就是說他根本就是omb04<>'MISC-FREIGHT' AND omb04 <>'MISC-M-DISCOUNT'

然後要記住一件事:null並不會參與匹配(除非附上IS NULL或IS NOT NULL條件)

所以這注定造成AND的結果會被返還FALSE,撈不出資料

 

至於第三張圖的SQL為什麼可以撈得出資料呢?因為那些撈不出資料的SQL都被優化器安排到Filter了,Filter的特性已於上段說明。

AND NOT EXISTS (SELECT 1 FROM ni.omb_file b WHERE b.omb04 IN ('MISC-FREIGHT','MISC-M-DISCOUNT') AND b.omb01 = a.omb01)這個陳述式會讓b.omb04 IN ('MISC-FREIGHT','MISC-M-DISCOUNT')該條件被優化器安排到Access,這意味著什麼呢?這意味著就沒有null參不參與匹不匹配的問題。

至於為何SQL優化器會將NOT IN謂詞安排到Filter呢?因為對於優化器來說使用IN才有決定要走INDEX的存取還是TABLE的存取(前者即為索引掃描、後者為全表掃描)的價值;而當使用NOT IN時,通常沒有選擇餘地,使用全表掃描對效能最好,所以就會直接丟到Filter囉~~

重點:

1.只有Filter才有返還TRUE/FALSE的問題,也只有在Filter下,AND的只要有一條件不符即會返還FALSE的結論才會成立。

2.當使用NOT IN謂詞時,Oracle SQL優化器幾乎不會使用Access而是使用Filter

 

本篇只是提供了一個可以透過改寫SQL而不動到資料(將NULL塞一個空白)的解決方案,至於詳細原理只能以後有時間再分享囉~~~[SQL] 當使用NOT IN碰到NULL會發生神馬事呢..

(反正就是如我之前有一篇談SQL優化的文章有提到,當查詢計畫出現Filter時應想辦法消除Filter)

arrow
arrow
    創作者介紹
    創作者 米血 的頭像
    米血

    米血的小天地

    米血 發表在 痞客邦 留言(0) 人氣()