mysql 線上not in查詢中的一個坑


今天早上開發又過來說,怎么有個語句一直沒有查詢出結果,數據是有的呀,並發來了如下的sql(為了方法說明,表名及查詢均做了修改):

select * from t2 where t2.course not in (select name from t1);

 

兩個表的數據如下:

mysql> select * from t1;
+----+------+
| id | name |
+----+------+
|  1 | NULL |
|  2 | chen |
|  3 | li   |
+----+------+
3 rows in set (0.00 sec)


mysql> select * from t2;
+------+--------+
| id   | course |
+------+--------+
|    1 | NULL   |
|    2 | chen   |
|    3 | math   |
+------+--------+
3 rows in set (0.00 sec)

 




所以按照要求來說,理論上應該顯示如下的數據才對:

+------+--------+
| id   | course |
+------+--------+
|    3 | math   |
+------+--------+
1 row in set (0.00 sec)

但實際的返回結果卻時empty

mysql>  select * from t2 where t2.course not in (select name from t1);
Empty set (0.00 sec)


這個可怪有意思了,不過一看到這種表中有null字段的都會先吐槽一下,一般來說字段都可以設置成非null的,而且效率也低,也要占用空間(mysql要記錄該條目是否為null)

既然已經這樣了,就分析分析:

mysql>  select * from t2 join t1 on t1.name=t2.course;
+------+--------+----+------+
| id   | course | id | name |
+------+--------+----+------+
|    2 | chen   |  2 | chen |
+------+--------+----+------+
1 row in set (0.00 sec)

注意:結果中並沒有出現course與name都為null的字段,即在mysql中null與null不相等。

 

mysql>  select * from t2 where t2.course not in (null);
Empty set (0.00 sec)

mysql>  select * from t2 where t2.course not in (null,'chen');
Empty set (0.00 sec)

注意:not in中包含有null時,結果集一直為Empty set

 

再看看下面的語句:

mysql>  select * from t2 where t2.course not in ('chen');
+------+--------+
| id   | course |
+------+--------+
|    3 | math   |
+------+--------+
1 row in set (0.00 sec)


mysql> select 1 > null;
+----------+
| 1 > null |
+----------+
|     NULL |
+----------+
1 row in set (0.00 sec)

注意,id=1,course=null的字段並沒有被查詢出來,null值與任何非null值比較都為null(非0非1)

如果非要查詢出包含null的字段,可以這樣:

mysql> select * from t2 where course is null or course not in ('chen');
+------+--------+
| id   | course |
+------+--------+
|    1 | NULL   |
|    3 | math   |
+------+--------+
2 rows in set (0.00 sec)

 

那么正確的姿勢應該是怎么寫呢?
用left join的方法,如下:

mysql> select t2.* from t2 left join t1 on t2.course=t1.name where t1.name is null ;
+------+--------+
| id   | course |
+------+--------+
|    1 | NULL   |
|    3 | math   |
+------+--------+
2 rows in set (0.00 sec)

 

當然如果t2表不包含null時,可以用字查詢接條件not null的方法:

mysql> select * from t2 where t2.course not in (select name from t1 where name is not null);
+------+--------+
| id   | course |
+------+--------+
|    3 | math   |
+------+--------+
1 row in set (0.00 sec)


有允許null的字段查詢時要多留個心眼,最好設計之初就不要出現允許null字段的存在。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM