2012-02-20 20 views
20

bảng của tôi được thiết lập một cái gì đó như thế này:Kiểm tra việc một mục không tồn tại trong bảng khác

table name: process 
fields: name, id_string 

table name: value_seach 
fields: id_string, value 

Tôi muốn xây dựng một tuyên bố chọn sẽ hiển thị tất cả các tên quá trình (với id_string tương ứng của nó) không có mục nhập trong value_search.

Id_string trong bảng quá trình có thể là null và vẫn có tên nhưng những thứ đó cần được loại trừ nếu có thể. Id_string trong value_search không bao giờ có thể là null

Làm cách nào để thực hiện việc này?

+0

Toán tử quan hệ bạn yêu cầu là chênh lệch bán a.k.a. chống tham gia. – onedaywhen

Trả lời

33

Nói chung nếu bạn muốn hàng không tồn tại trong bảng khác, sau đó LEFT JOIN bảng khác và WHERE .. IS NULL đến một cột trên bảng thứ hai. Ngoài ra bạn đã đề cập rằng bạn không muốn các hàng có process.id_string là NULL.

SELECT p.name, p.id_string 
FROM 
    process p 
    LEFT JOIN value_search v 
     ON v.id_string = p.id_string 
WHERE 
    v.id_string IS NULL 
    AND p.id_string IS NOT NULL 

Điều này được gọi là chống tham gia.

+0

Điều này rất hữu ích. Cảm ơn bạn. – 1man

2
SELECT 
    name, 
    id_string 
FROM process 
WHERE id_string IS NOT NULL AND id_string NOT IN SELECT id_string FROM value_seach 
+0

Điều này sẽ hoạt động nhưng sẽ chậm hơn nhiều so với kết nối bên ngoài. –

+0

đồng ý câu trả lời của bạn tốt hơn – alexsuslin

4

Truy vấn bạn muốn trông giống như thế này. Lưu ý rằng JOIN sẽ nhanh hơn đáng kể so với truy vấn phụ trong mệnh đề WHERE.

SELECT p.name, p.id_string 
FROM process p 
LEFT OUTER JOIN value_search v 
    ON p.id_string = v.id_string 
    AND p.id_string IS NOT NULL 
    AND v.id_string IS NULL 

Một biến thể giá trị ngang nhau của các truy vấn trên sẽ là:

SELECT p.name, p.id_string 
FROM process p 
LEFT OUTER JOIN value_search v 
    ON p.id_string = v.id_string 
WHERE 
    p.id_string IS NOT NULL 
    AND v.id_string IS NULL 
24

Tôi tin rằng việc sử dụng Not Exists sẽ là lựa chọn tốt nhất của bạn tại đây.

SELECT p.name, p.id_string 
FROM process p 
WHERE 
    NOT p.id_string IS NULL AND 
    NOT EXISTS(
      SELECT NULL 
      FROM value_search v 
      WHERE p.id_string = v.id_string) 
+1

Thao tác này sẽ hoạt động nhưng sẽ chậm hơn nhiều so với kết nối bên ngoài. –

+4

@BrianDriscoll Không có gì, 'Left external join' với' null' check và 'Not Exists' sẽ tạo ra cùng một kế hoạch truy vấn ngay cả khi bảng bên trái có giá trị null hay không. Xem: http://explainextended.com/2009/09/17/not-in-vs-not-exists-vs-left-join-is-null-oracle/ để biết thêm thông tin. Tôi các giá trị được đảm bảo là 'không null',' Left join', 'Not exist' và' Not in' sẽ tạo cùng một kế hoạch truy vấn. – Magnus

+4

@BrianDriscoll Cũng lưu ý rằng đối với nhiều DBMS khác, chẳng hạn như SQL server, kiểm tra 'Left Outer Join' với' NULL' sẽ mang lại hiệu suất tồi tệ nhất vì nó không thể phân biệt được một ANTI JOIN. – Magnus

Các vấn đề liên quan