2012-05-16 46 views
6

Tôi có bảng này:hành vi kỳ lạ với NOT IN

select count(distinct clean_deep_link) from tbl_1; 
+---------------------------------+ 
| count(distinct clean_deep_link) | 
+---------------------------------+ 
|       121211 | 
+---------------------------------+ 

Tôi có truy vấn này:

select count(1) from tbl_1 where clean_deep_link IN 
    (select clean_deep_link from tbl_2); 

+----------+ 
| count(1) | 
+----------+ 
| 66360 | 
+----------+ 

Nhưng khi tôi thay đổi truy vấn để not in nó sẽ trả về một tập rỗng:

select count(1) from tbl_1 
where clean_deep_link not in (select clean_deep_link from tbl_2); 
+----------+ 
| count(1) | 
+----------+ 
|  0 | 
+----------+ 

Làm cách nào có thể? nếu truy vấn con chứa khoảng một nửa số bản ghi, không nên not truy vấn phụ chứa nửa còn lại? Tôi đang thiếu gì ở đây?

Cảm ơn

+0

Hãy thử 'select count (*), đếm (1) TỪ tbl_1 ... ' – vyegorov

+0

Bạn có null trong cột? 'SELECT COUNT (*) FROM tbl_1 WHERE clean_deep_link IS NULL' trả về cái gì? –

+2

Hay nói cách khác, có ba nửa trong một bảng SQL. –

Trả lời

9

Tôi cho rằng tbl_1.clean_deep_linkNULL cho phần còn lại của các hàng.

Các giá trị này không phải là IN cũng không phải NOT IN truy vấn phụ của bạn.


Lý do khác có thể là bạn có NULL trong tbl_2.clean_deep_link.

hãy thử như sau:

select count(1) from tbl_1 
where clean_deep_link not in (select clean_deep_link 
           from tbl_2 WHERE clean_deep_link IS NOT NULL); 

Vấn đề với NULL là nó không phải là =, cũng không <> bất kỳ giá trị khác (bao gồm NULL).

Khi kiểm tra NOT IN, MySQL cần kiểm tra từng giá trị trong tbl_1 rằng nó không được chứa trong tbl_2 và do đó kiểm tra xem chúng có phải là <> hay không.

giá trị của bạn là không<> NULL, vì vậy họ đã khôngNOT IN.

Xem thêm: Using NOT IN operator with null values


Kiểm tra ví dụ trong SQL Fiddle.

+0

là tbl_1 ... – WeaselFox

+0

Có, đã có một bản ghi duy nhất trong tbl_2 có NULL cho clean_deep_link ... khi tôi đã xóa bản ghi đó, truy vấn con hoạt động tốt. Làm sao điều đó có thể gây ra nó? – WeaselFox

+0

Cố gắng giải thích nó trong bản cập nhật gần đây của tôi, hy vọng nó không quá khó hiểu;) Xem xét việc đặt một ràng buộc 'NOT NULL' trên' tbl_2.clean_deep_link' để tránh vấn đề này. –

2

Các cột NULL trong MySQL được tính là khác biệt, vì vậy, ba giá trị NULL đều được xem là khác biệt.

Như đã đề cập ở nơi khác, bạn không thể so sánh NULL với các giá trị khác bằng cách sử dụng toán tử so sánh thông thường, trong đó INNOT IN.

Các nhà khai thác sau đây có thể xử lý NULL giá trị

0
SELECT COUNT(*) - COUNT(1) 
FROM tbl_1 
WHERE clean_deep_link IN (
    SELECT clean_deep_link 
    FROM tbl_2 
);