In和exists使用及效能分析(一):in的使用
本節主要討論in的原理及使用,以及常見的錯誤的觀點。
一、in的使用
1.1 in的使用
1.1.1 內、外兩表關聯欄位都非空
SQL> select * from tb1;
T1 NAME1
---------- ----------
1 1
2 2
SQL> select * from tb2;
T2 NAME2
---------- ----------
2 2
SQL> select count(1) from tb1 where t1 in (select t2 from tb2);
--T1=2的記錄符合條件,結果符合常規思維
COUNT(1)
----------
1
SQL> select count(1) from tb1 where t1 not in (select t2 from tb2);
--T1=1的記錄符合條件,結果符合常規思維
COUNT(1)
----------
1
1.1.2 當外表關聯欄位無空值、內表關聯列表有空值時
SQL> select * from tb1;
T1 NAME1
---------- ----------
1 1
2 2
SQL> select * from tb2;
T2 NAME2
---------- ----------
2 2
3
SQL> select count(1) from tb1 where t1 in (select t2 from tb2);
--T1=2的記錄符合條件,結果符合常規思維
COUNT(1)
----------
1
SQL> select count(1) from tb1 where t1 not in (select t2 from tb2);
--無記錄符合條件,結果不符合常規思維
COUNT(1)
----------
0
SQL> select count(1) from tb1 where t1 in (select t2 from tb2 where t2 is not null);
--T1=2的記錄符合條件,結果符合常規思維
COUNT(1)
----------
1
SQL> select count(1) from tb1 where t1 not in (select t2 from tb2 where t2 is not null);
--T1=2的記錄符合條件,結果符合常規思維
COUNT(1)
----------
1
1.1.3當外表關聯欄位有空值、內表關聯列表無空值時
SQL> select * from tb1;
T1 NAME1
---------- ----------
1 1
1
2 2
SQL> select * from tb2;
T2 NAME2
---------- ----------
2 2
3 3
SQL> select count(1) from tb1 where t1 in (select t2 from tb2);
--T1=2的記錄符合查詢條件,符合常規思維
COUNT(1)
----------
1
SQL> select count(1) from tb1 where t1 not in (select t2 from tb2);
--只有T1=2的記錄符合查詢條件,與常規思維相悖
COUNT(1)
----------
1
1.1.4 當內、外表的關聯欄位都有空值時
SQL> select * from tb1;
T1 NAME1
---------- ----------
1 1
2 2
3
SQL> select * from tb2;
T2 NAME2
---------- ----------
2 2
3
SQL> select count(1) from tb1 where t1 in (select t2 from tb2);
--只有t1=2的記錄符合條件,與常規思維相悖
COUNT(1)
----------
1
SQL> select count(1) from tb1 where t1 not in (select t2 from tb2);
--沒有符合條件的記錄,與常規思維相悖
COUNT(1)
----------
0
SQL> select count(1) from tb1 where t1 in (select t2 from tb2 where t2 is not null);
--只有t1=2的記錄符合條件,符合常規思維
COUNT(1)
----------
1
SQL> select count(1) from tb1 where t1 not in (select t2 from tb2 where t2 is not null);
--只有t1=1的記錄符合條件,與常規思維相悖
COUNT(1)
----------
1
1.1.5 外表無記錄
SQL> select * from tb1;
T1 NAME1
---------- ----------
SQL> select * from tb2;
T2 NAME2
---------- ----------
2 2
3 3
SQL> select count(1) from tb1 where t1 in (select t2 from tb2);
--無記錄返回
COUNT(1)
----------
0
SQL> select count(1) from tb1 where t1 not in (select t2 from tb2);
--無記錄返回
COUNT(1)
----------
0
這裡很容易理解,無論條件成立與否,因為外表無記錄,索引返回記錄數為0
1.1.6 內表無記錄
SQL> select * from tb1;
T1 NAME1
---------- ----------
1 1
2 2
SQL> select * from tb2;
T2 NAME2
---------- ----------
SQL> select count(1) from tb1 where t1 in (select t2 from tb2);
--所有記錄都不符合條件,結果符合常規思維
COUNT(1)
----------
0
SQL> select count(1) from tb1 where t1 not in (select t2 from tb2);
--所有記錄都符合條件,結果符合常規思維
COUNT(1)
----------
2
1.2 in運算總結:
1.2.1單列作in運算時
1. col in (v1,v2,...vn) 相當於 (col=v1 or col=v2 or ...col=vn)
col not in (v1,v2,...vn) 相當於 (col<>v1 and col<>v2 and ...col<>vn)
2. 當in 列表的記錄數大於0,且in列表(vn)有null值時,則oracle在處理 in 的時候轉換成:
(col=v1 or col=v2 or col=null or ...col=vn)
所以,in列表有null值不會引起與常規思維不一樣的結果
3. 當not in 列表的記錄數大於0,且not in列表有null值時,oracle在處理not in 當時候轉換成:
(col<>v1 and col<>v2 and col<>null and ...col<>vn),由於oracle中null是一個非常特殊的值,null與任何值做算術運算子比較都返回false,由於多個條件是用and連線的,所以這種情況整個條件是false,也就不會有記錄返回。
這種情況是最容易搞混和不理解的。
4. 當in/not in 列表的記錄數大於0,且col是null值時,null與任何值做算術運算子比較都返回false,根據in和not in的處理方式可知,無論是in運算還是not in 運算,oracle不會有任何記錄返回。也就是說oracle在處理時相當於把col是null的記錄忽略不作處理。
5. 當in/not in 列表的記錄數為0時(注意與in/not in列表全為空不同),in運算相當於條件1=2;not in運算相當於1=1;
6. 在not in操作中,可以在子查詢中加入col is not null使得有記錄返回
1.2.2 多列作in運算時
1. (col1,col2) in ((v11,v12),(v21,v22),...(vn1,vn2))相當於
((col1=v11 and col2=v12) or (col1=v21 and col2=v21) ... or (col1=vn1 and col2=vn2))
(col1,col2) not in ((v11,v12),(v21,v22),...(vn1,vn2))相當於
((col1<>v11 or col2<>v12) and (col1<>v21 or col2<>v22) and ...(col1<>vn1 or col2<>vn2))
2. 多列in運算當原理和單列一樣,把col1和col2看作一個整體col,把vn1和vn2看作一個整體vn就相當於單列作in運算了。
3. 多列運算比較特殊當兩種情況是col1和col2都為null時,相當於單列中都col為null,oracle在處理這種情況時,相當於忽略這條記錄;
當vn1和vn2都為null時,相當於單列運算中vn為null的情況,在作in運算時不會影響返回結果,但在作not in運算時不會有任何記錄返回。
4. 當col1和col2中有一個為null時,作in運算時oracle相當於把該記錄忽略不計,因為(null or null or null...)結果是null。(not in不能忽略)
5. 當col1和col2其中一個為null,且另一個的值在包含在not in列表中時,在作not in運算時oracle相當於把該記錄忽略不計(null && true/false結果是null)。
6. 在not in操作中,可以在子查詢加入((col1 is not null) or (col2 is not null))使得有結果返回
7. 以上小結適用於in/not in 列表的記錄數大於0的情況
8. any、all運算與in類似
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/231499/viewspace-63763/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- In和exists使用及效能分析(二):exists的使用
- In和exists使用及效能分析(三):in和exists的效能分析
- [精選] SQL中的IN與NOT IN、EXISTS與NOT EXISTS的區別及效能分析SQL
- sql中in和exists的原理及使用場景。SQL
- 對線面試官:SQL中的IN與NOT IN、EXISTS與NOT EXISTS的區別及效能分析面試SQL
- Oralce 使用SQL中的exists 和not exists 用法詳解SQL
- perf及火焰圖的使用,效能分析
- Oracle中exists和in的效能差異Oracle
- 使用Android Profile做效能分析及優化Android優化
- Unity效能分析(一)流程與工具的使用Unity
- mysql 關於exists 和in分析MySql
- golang 使用pprof和go-torch做效能分析Golang
- MySQL-09.效能分析工具的使用MySql
- perf效能分析工具使用分享
- 使用pprof進行效能分析
- ThreadPoolExecutor的使用及原始碼分析thread原始碼
- STL的map使用和分析
- Laravel Event的分析和使用Laravel
- mybatis exists 中使用代替in關鍵字MyBatis
- zCloud使用技巧:如何使用效能下鑽功能分析SQL效能問題CloudSQL
- Goroutine 和 Channel 的的使用和一些坑以及案例分析Go
- iOS使用Instrument Time Profiler工具分析和優化效能問題iOS優化
- 使用window.performance分析頁面效能ORM
- InheritedWidget的使用和原始碼分析原始碼
- 伺服器效能指標(三)——記憶體使用分析及問題排查伺服器指標記憶體
- Spring事務原始碼分析專題(一)JdbcTemplate使用及原始碼分析Spring原始碼JDBC
- 一起分析Nginx 日誌及效能排查Nginx
- webpack動態匯入和require.context分析及使用注意WebUIContext
- new 和 malloc 的區別 及使用
- DRF檢視的使用及原始碼流程分析原始碼
- 使用 XDebug + Webgrind 進行 PHP 程式效能分析WebPHP
- git使用報錯fatal: remote origin already exists.GitREM
- 蘊含式(包含EXISTS語句的分析)
- 效能測試工具Lmbench的使用和下載
- golang 中 channel 的詳細使用、使用注意事項及死鎖分析Golang
- not in 和 not exists 比較和用法
- 系統級效能分析工具perf的介紹與使用
- 使用JDK自帶的VisualVM進行Java程式的效能分析JDKLVMJava