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