【原创】关于not in的一些事情
早上到公司,收到一條cocall消息,是某哥們遇到的疑惑,可能很多新手并不知情:
請教個問題 我執行 1. select * from t_htgl_htpswj t where t.c_wjmc = '山西'; 結果是 存在一條記錄 2. select * from t_htgl_fj t where t.c_wjmc = '山西'; 結果是不存在記錄 3. 為什么執行select count(*) from t_htgl_htpswj htpswj where htpswj.c_wjmc not in (select fj.c_wjmc from t_htgl_fj fj ) 按照 1,2的執行結果,3的結果應該是至少是1才對呀,為什么實際執行結果是0呢。。。。 C_WJMC的類型都是VARCHAR(200) 很詭異的是 第三個查詢,我如果用下面這個語句統計查詢又是可以查詢到結果的。。。。 select count(*) from t_htgl_htpswj htpswj where htpswj.c_wjmc not in (select fj.c_wjmc from t_htgl_fj fj where fj.n_xsxm_htps is not null) 我添加的這個子查詢的條件好像和整體查詢沒有關系呀。。。對于這個問題,需要了解以下兩點內容:
1.null到底是個什么東西?
2.not in是如何執行的,什么原理?
下面看第一點:
1.null到底是個什么東西?我們知道在存儲過程中:select a into b from t1 where c='';--如果返回的記錄為零,那么會報錯,此時實際上返回的就是一個null,一般在前面加一個count的判斷再into。
null在oracle中代表什么都不是,空記錄,這個地球人都知道,關鍵是在運算中,null和任何值的算術或者邏輯運算結果都是null,而且它和任何值都不相等,也非不相等,和自身也不相等,如:
select * from t1 where a=null;--查不到正確的記錄
select * from t1 where null=null;--查不到記錄。因此在判斷空與非空時使用is null或者is not null來判斷,以下是有個哥們讓優化的sql:
這樣寫是不對的,會獲取不到正確的記錄。應該這樣寫:
select * from t1 where a is null or b is not null;
插播一點,is null和is not null判斷都是無法使用索引的,tom的書上有個很不錯的提議,就是將null以一個值來代替,如果某列代碼值為空,如不妨以-1來代表null,字符的話也可以以其他值(如‘null’)代替,這樣在判斷的時候可以使用索引。
2.not in 是如何執行的?
先看in是如何執行的:
如:
如果條件有null呢?
select * from t where a in(1,2,3,null);等價于: select * from t where a=1 or a=2 or a=3 or a=null; --這是沒有問題的,一般一樣可以得到正確結果,因為a和null不相等,因此null值會被忽略那么not in呢?
select * from t where a not in(1,2,3);--等價于 select * from t where a !=1 and a!=2 and a!=3;如果這個條件中有null值呢?
select * from t where a not in(1,2,3,null);--等價于 select * from t where a !=1 and a!=2 and a!=3 and a!=null;看a!=null,這個條件是不成立的,始終都是false,所以導致整個表達式為false,所以查不到任何記錄。
回到開頭的問題:
"select fj.c_wjmc from t_htgl_fj fj",這個sql中c_wjmc返回的結果是否包含null值呢?
我們執行以下sql:
select count(*) from t_htgl_fj fj where fj.c_wjmc is null;
----------
COUNT(*)
30
----------
所以,子查詢中的c_wjmc存在null值,導致整個where的邏輯運算結果為false,因此沒有返回任何結果。
那么為什么
select fj.c_wjmc from t_htgl_fj fj where fj.n_xsxm_htps is not null;--這個查詢中c_wjmc有沒有空值呢?
執行以下查詢:
這個查詢中恰巧n_xsxm_htps is not null將所有的c_wjmc為null的記錄過濾掉了,所以子查詢中沒有null值,所以能查到正確的結果。
結論:在not in的查詢中,如果子查詢結果中包含null值,將查不到記錄,not in無法處理null值。因此可以使用exists,如果非要使用not in,也要保證在子查詢中將null值過濾掉。
通常情況下,exists效率要高于in,而且exists可以準確的處理null值(其實是事先過濾掉罷了,不再贅述),關于exists和in的使用場景和區別,見另一篇帖子:
轉載于:https://www.cnblogs.com/zhangxsh/p/3494414.html
總結
以上是生活随笔為你收集整理的【原创】关于not in的一些事情的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用 OpenCV 构建车辆计数器系统
- 下一篇: Screen, Viewport 和 R