A. oracle中in,not in和exists,not exists之間的區別
1、關於在 Oracle8i 時代中in和exists的區別
這里有條sql語句:select * from A where id in(select id from B)
以上查詢使用了in語句,in()只執行一次,它查出B表中的所有id欄位並緩存起來.之後,檢查A表的id是否與B表中的id相等,如果相等則將A表的記錄加入結果集中,直到遍歷完A表的所有記錄;
它的查詢過程類似於以下過程
List resultSet=[];
Array A=(select * from A);
Array B=(select id from B);
for(int i=0;i<A.length;i++) {
for(int j=0;j<B.length;j++) {
if(A[i].id==B[j].id) {
resultSet.add(A[i]);
break;
}
}
}
return resultSet;
可以看出,當B表數據較大時不適合使用in(),因為它會B表數據全部遍歷一次.
如:A表有10000條記錄,B表有1000000條記錄,那麼最多有可能遍歷10000*1000000次,效率很差.
再如:A表有10000條記錄,B表有100條記錄,那麼最多有可能遍歷10000*100次,遍歷次數大大減少,效率大大提升.
結論1:in()適合B表比A表數據小的情況
這里還有一條SQL語句: select a.* from A a where exists(select 1 from B b where a.id=b.id)
以上查詢使用了exists語句,exists()會執行A.length次,它並不緩存exists()結果集,因為exists()結果集的內容並不重要,重要的是結果集中是否有記錄,如果有則返回true,沒有則返回false.
它的查詢過程類似於以下過程
List resultSet=[];
Array A=(select * from A)
for(int i=0;i<A.length;i++) {
if(exists(A[i].id) { //執行select 1 from B b where b.id=a.id是否有記錄返回
resultSet.add(A[i]);
}
}
return resultSet;
結論2:exists()適合B表比A表數據大的情況
當B表比A表數據大時適合使用exists(),因為它沒有那麼遍歷操作,只需要再執行一次查詢就行.
如:A表有10000條記錄,B表有1000000條記錄,那麼exists()會執行10000次去判斷A表中的id是否與B表中的id相等.
如:A表有10000條記錄,B表有100000000條記錄,那麼exists()還是執行10000次,因為它只執行A.length次,可見B表數據越多,越適合exists()發揮效果.
再如:A表有10000條記錄,B表有100條記錄,那麼exists()還是執行10000次,還不如使用in()遍歷10000*100次,因為in()是在內存里遍歷比較,而exists()需要查詢資料庫,我們都知道查詢資料庫所消耗的性能更高,而內存比較很快.
當A表數據與B表數據一樣大時,in與exists效率差不多,可任選一個使用.
In適合內外表都很大的情況,exists適合外表結果集很小的情況。
In和exists對比:
若子查詢結果集比較小,優先使用in,若外層查詢比子查詢小,優先使
用exists。因為若用in,則Oracle會優先查詢子查詢,然後匹配外層查詢,
若使用exists,則oracle會優先查詢外層表,然後再與內層表匹配。最優化
匹配原則,拿最小記錄匹配大記錄
2、關於在 Oracle8i 之後 時代中in和exists的區別
in 是把外表和內表作hash join,而exists是對外表作loop,每次loop再對內表進行查詢。
一直以來認為exists比in效率高的說法是不準確的。
如果查詢的兩個表大小相當,那麼用in和exists差別不大。
如果兩個表中一個較小,一個是大表,則子查詢表大的用exists,子查詢表小的用in:
例如:表A(小表),表B(大表)
1:
select * from A where cc in (select cc from B)
效率低,用到了A表上cc列的索引;
select * from A where exists(select cc from B where cc=A.cc)
效率高,用到了B表上cc列的索引。
相反的
2:
select * from B where cc in (select cc from A)
效率高,用到了B表上cc列的索引;
select * from B where exists(select cc from A where cc=B.cc)
效率低,用到了A表上cc列的索引。
帶in的關聯子查詢是多餘的,因為in子句和子查詢中相關的操作的功能是一樣的。如:
select staff_name from staff_member where staff_id in
(select staff_id from staff_func where staff_member.staff_id=staff_func.staff_id);
為非關聯子查詢指定exists子句是不適當的,因為這樣會產生笛卡乘積。如:
select staff_name from staff_member where staff_id
exists (select staff_id from staff_func);
not in 和not exists
如果查詢語句使用了not in 那麼內外表都進行全表掃描,沒有用到索引;
而not extsts 的子查詢依然能用到表上的索引。
所以無論哪個表大,用not exists都比not in要快。
盡量不要使用not in子句。使用minus 子句都比not in 子句快,雖然使用minus子句要進行兩次查詢:
select staff_name from staff_member where staff_id in (select staff_id from staff_member minus select staff_id from staff_func where func_id like '81%');
in 與 "=" 的區別
select name from student where name in ('zhang','wang','li','zhao');
與
select name from student where name='zhang' or name='li' or name='wang' or name='zhao'
的結果是相同的。
3、關於在 Oracle8i 之後 時代中in和exists的區別
在ORACLE 11G大行其道的今天,還有很多人受早期版本的影響,記住一些既定的規則,
1.子查詢結果集小,用IN
2.外表小,子查詢表大,用EXISTS
這是完全錯誤的觀點。在8i時代,這經常是正確的,但是現在已經11G了,馬上12C就要面世了。其實在ORACLE 9i CBO就已經優化了IN,EXISTS的區別,ORACLE優化器有個查詢轉換器,很多SQL雖然寫法不同,但是ORACLE優化器會根據既定規則進行查詢重寫,重寫為優化器覺得效率最高的SQL,所以可能SQL寫法不同,但是執行計劃卻是完全一樣的。
IN與EXISTS有一點要記住:IN一般是用於非相關子查詢,而EXISTS一般用於相關子查詢。當然IN也可以用於相關子查詢,EXISTS也可以用於非相關子查詢。但是這區別很重要,雖然優化器很強大,但是查詢轉換是有一定的限制的,在EXISTS性能低下,無法進行相關查詢轉換,比如不能UNNEST SUBQUERY,那麼可能我們需要改寫SQL,通常可以用IN/JOIN等改寫相關子查詢,或對於含有OR的SEMI JOIN改為UNION ALL/UNION的形式。
下面就用例子說明一下:
DROP TABLE a;
DROP TABLE b;
CREATE TABLE a AS SELECT * FROM hr.employees;
CREATE TABLE b AS SELECT * FROM hr.employees;
--反復插入,構造20萬行+
INSERT INTO a SELECT * FROM a;
INSERT INTO b SELECT * FROM a;
COMMIT;
BEGIN
dbms_stats.gather_table_stats(ownname => USER,tabname => 'a',estimate_percent => 100,cascade => TRUE);
dbms_stats.gather_table_stats(ownname => USER,tabname => 'b',estimate_percent => 100,cascade => TRUE);
END;
/
1.測試IN,EXISTS在簡單查詢中,是等價的
SQL> set autotrace traceonly exp
SQL> SELECT * FROM a
2 WHERE EXISTS(
3 SELECT 1 FROM b WHERE a.employee_id=b.employee_id);
執行計劃
----------------------------------------------------------
Plan hash value: 2317816356
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 217K| 15M| 1375 (2)| 00:00:17 |
|* 1 | HASH JOIN | | 217K| 15M| 1375 (2)| 00:00:17 |
| 2 | SORT UNIQUE | | 217K| 848K| 126 (1)| 00:00:02 |
| 3 | INDEX FAST FULL SCAN | IDX2_B | 217K| 848K| 126 (1)| 00:00:02 |
| 4 | TABLE ACCESS FULL | A | 217K| 14M| 620 (1)| 00:00:08 |
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."EMPLOYEE_ID"="B"."EMPLOYEE_ID")
SQL> SELECT * FROM a
2 WHERE a.employee_id IN (SELECT b.employee_id FROM b);
執行計劃
----------------------------------------------------------
Plan hash value: 2317816356
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 217K | 15M| 1375 (2) | 00:00:17 |
|* 1 | HASH JOIN | | 217K | 15M| 1375 (2) | 00:00:17 |
| 2 | SORT UNIQUE | | 217K | 848K| 126 (1) | 00:00:02 |
| 3 | INDEX FAST FULL SCAN | IDX2_B | 217K | 848K| 126 (1) | 00:00:02 |
| 4 | TABLE ACCESS FULL | A | 217K | 14M| 620 (1) | 00:00:08 |
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."EMPLOYEE_ID"="B"."EMPLOYEE_ID")
可以看出,兩個計劃完全沒有區別。類似於ORACLE查詢重寫為:
SELECT a.* FROM a,(SELECT DISTINCT b.employee_id FROM b) b1 WHERE a.employee_id=b1.employee_id;
結語:討論SQL語句:select * from A where id in (1,2,3,4,5,6,7,8,9) 中 在Oracle8i 版本之後的Oracle資料庫中性能是一樣的。
B. sql中的not in語句怎樣用mysql表示
你的語句可以這樣寫:
select * from users where userid not in (select userid from users limit 3) limit 3
但是,如果你是要返回每3個一頁的第二頁,用下面的語句更好:
select * from users limit 3,3
這就是mysql比許多資料庫都更適合用於internet的原因之一:方便的支持結果分頁。
C. sql語言中與not in等價的操作符是什麼
select * from a where idno not in(select idno from b)
等價於
select * from a where not exists(select 1 from b where idno=a.idno)
查詢結果是等價的,但是運行效率還是有區別
D. sql中與not in功能等價的運算符是
< >ALL 與所有都不相等,與NOT IN的意思相同。
< >是不等於的意思
E. 11. 在SQL中,與「NOT IN」等價的操作符是( ) A. < >ALL B. < >SOME C. = SOME D. = ALL
選A
<> ALL和所有的 都不相等, 也就是說沒有在另一張表裡出現;
<> some和部分不相等 一般用來看 兩個集合 有沒有不同元素;
= some和部分相等 一般用來看有沒有交集;
= ALL和所有相等 一般用來看兩個集合是否相等;
SQL風格統一
SQL可以獨立完成資料庫生命周期中的全部活動,包括定義關系模式、錄入數據、建立資料庫、査詢、更新、維護、資料庫重構、資料庫安全性控制等一系列操作,這就為資料庫應用系統開發提供了良好的環境,在資料庫投入運行後,還可根據需要隨時逐步修改模式,且不影響資料庫的運行,從而使系統具有良好的可擴充性。
以上內容參考:網路-結構化查詢語言
F. sql not in not exists
因為not in不能判斷含有null的值,not exists與not in (select zd2 from #gaolima where zd2 is not null)才是等價的
G. 證明在SQL中,all 等價於not in 資料庫概論上的題
用反證法.
all的反例是=any,意思是和要查詢的集合裡面的任意一個相等,也就是肯定存在於裡面的意思,和in是相同的,所以就和not in等價了,因為in的反例是not in
就是用負負得正的思想,最外層是反,裡面的一層是反,其實就是相等
H. sql語句中in的用法
IN 操作符允許我們在 WHERE 子句中規定多個值。
SQL IN 語法:
SELECT column_name(s)
FROM table_name
WHERE column_name IN (value1,value2,...)
(8)sql中notin等價擴展閱讀:
1、IN 與 = ANY 等價,均表示,變數在(子查詢)列表之中,即 a IN (table B) 表示 a = ANY B.b
2、NOT IN 與 <> ALL 等價,而不等於<> ANY,前兩者均表示,變數不在(子查詢)列表之中,即 a NOT IN (table B) 表示 a <> ALL B.b。而如果a <> ANY B.b,則只要任意一個b<>a就true了。
3、IN 與 EXISTS 的性能區別主要來自,IN 會編列子查詢的每行記錄,然後再返回,而EXISTS 則只要遇到第一個滿足條件的記錄就馬上返回。
I. SQL <>some是什麼意思和not in 的區別是什麼
<>後邊只能跟一個值
not in (這里能跟一堆值)
再就沒區別了
不過<>要是想和not in效果一致的話,可以配合or一起用
J. SQL中not in的等價操作符是什麼啊
注意 任何帶的not in 的語句可以使用 not exists 替換!!
但not exists 的則不一定
答案是A