SQL 查詢語句中in與not in查出來的條數不是互補的

1、in與not in不是互補的

SQL 查詢語句中in與not in查出來的條數不是互補,即用in查出來的條數不等於總數減去not in查出來的條數。java

例如:數據庫表中有10條記錄,用select count(*) from person where name in('xiaochen'); 查出來的記錄條數是2,而用select count(*) from person where name not in('xiaochen');查出來的記錄條數是2,也就是說1條記錄「沒了」;mysql

形成這結果緣由是:person表中的name字段的值是存在null,它既不在in的記錄範圍內,也不在not in的範圍內,因此沒查出。sql

person表數據庫

id                 name             ageoop

1                  xiaochen        22spa

2                  dick               19code

3                  fsdfsdfss        22orm

4                  null               24排序

5                  xiaochen        22索引

select count(*) from person where name in('xiaochen'); --結果是:2

select count(*) from person where name not in('xiaochen'); --結果是:2

select count(*) from person; --結果是:5 

2、針對in與not in不是互補的補救方法---not exists

in和exists  

in :把外表和內表做hash 鏈接

Exists:對外表做loop循環,每次loop循環再對內表進行查詢。


效率比

一直以來認爲exists比in效率高的說法是不許確的。  

若是查詢的兩個表大小至關,那麼用in和exists差異不大。  

若是兩個表中一個較小,一個是大表,則子查詢表大的用exists,子查詢表小的用in:  

例如:表A(小表),表B(大表)

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列的索引。  

相反的:表A(大表),表B(小表)

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列的索引。 



not in 和not exists    

not in :內外表都進行全表掃描,沒有用到索引;

not extsts :子查詢依然能用到表上的索引。

因此不管那個表大,用not exists都比not in要快。   

  

not in 邏輯上不徹底等同於not exists,若是你誤用了not in,當心你的程序存在致命的BUG:   

請看下面的例子:  

CREATE TABLE `t1` (

  `c1` DECIMAL(10,0) DEFAULT NULL,

  `c2` DECIMAL(10,0) DEFAULT NULL

) ENGINE=INNODB DEFAULT CHARSET=utf8


CREATE TABLE `t2` (

  `c1` DECIMAL(10,0) DEFAULT NULL,

  `c2` DECIMAL(10,0) DEFAULT NULL

) ENGINE=INNODB DEFAULT CHARSET=utf8

  

INSERT INTO t1 VALUES (1,2);  

INSERT INTO t1 VALUES (1,3);  

INSERT INTO t2 VALUES (1,2);  

INSERT INTO t2 VALUES (1,NULL);  

 

select * from t1 where c2 not in (select c2 from t2);  

no rows found  

select * from t1 where not exists (select 1 from t2 where t1.c2=t2.c2);  

c1 c2  

1 3  

 

正如所看到的,not in 出現了不指望的結果集,存在邏輯錯誤。若是看一下上述兩個select語句的執行計劃,也會不一樣。後者使用了hash_aj。  

所以,請儘可能不要使用not in(它會調用子查詢),而儘可能使用not exists(它會調用關聯子查詢)。

若是子查詢中返回的任意一條記錄含有空值,則查詢將不返回任何記錄,正如上面例子所示。  

除非子查詢字段有非空限制,這時可使用not in ,而且也能夠經過提示讓它使用hasg_aj或merge_aj鏈接 


3、mysql中in排序問題(MySQL 查詢in操做,查詢結果按in集合順序顯示)

在mysql中,用in查詢,查詢結果,並非按照id自己順序出,而是亂序的。以下:

SELECT question_id FROM question WHERE question_id IN (164,165,166,161,162,163,167)

可結果以下:

若是須要結果根據傳入的ids順序出,須要加 order by field(question_id,164,165,166,161,162,163,167) 指定排序

SELECT question_id FROM question WHERE question_id IN (164,165,166,161,162,163,167)
ORDER BY FIELD(question_id,164,165,166,161,162,163,167)

相關文章
相關標籤/搜索