CHỌN * NƠI KHÔNG TỒN TẠI


94

Tôi nghĩ rằng tôi đang đi đúng hướng với cái này ... Xin hãy nhớ với tôi vì SQL của tôi không phải là tốt nhất

Tôi đang cố gắng truy vấn cơ sở dữ liệu để chọn mọi thứ từ một bảng trong đó các ô nhất định không tồn tại trong bảng khác. Điều đó không có nhiều ý nghĩa nhưng tôi hy vọng đoạn mã này sẽ

SELECT * from employees WHERE NOT EXISTS (SELECT name FROM eotm_dyn)

Vì vậy, về cơ bản tôi có một bảng với danh sách nhân viên và thông tin chi tiết của họ. Sau đó, một bảng khác với một số chi tiết khác, bao gồm cả tên của họ. Trường hợp không có tên trong bảng eotm_dyn, nghĩa là không có mục nhập cho họ, tôi muốn xem chính xác họ là ai, hay nói cách khác, xem chính xác họ còn thiếu gì.

Truy vấn trên không trả về gì, nhưng tôi biết có 20 tên bị thiếu nên rõ ràng là tôi đã hiểu không đúng.

Có ai giúp được không?

Câu trả lời:


160

Bạn đã không tham gia vào bảng trong truy vấn của mình.

Truy vấn ban đầu của bạn sẽ luôn không trả lại gì trừ khi không có bản ghi nào trong đó eotm_dyn, trong trường hợp đó, nó sẽ trả về mọi thứ.

Giả sử các bảng này nên được nối vào employeeID, hãy sử dụng như sau:

SELECT  *
FROM    employees e
WHERE   NOT EXISTS
        (
        SELECT  null 
        FROM    eotm_dyn d
        WHERE   d.employeeID = e.id
        )

Bạn có thể nối các bảng này với một LEFT JOINtừ khóa và lọc ra những từ khóa NULL, nhưng điều này có thể sẽ kém hiệu quả hơn so với việc sử dụng NOT EXISTS.


30
Tôi cần "WHERE KHÔNG TỒN TẠI" hai lần một năm và tôi luôn quên cách sử dụng chính xác nó. Cảm ơn - ví dụ này sẽ được đánh dấu ngay bây giờ.
Mateng

1
Ai đó có thể vui lòng cung cấp tài liệu tham khảo cho "LEFT JOIN + NULL filter kém hiệu quả hơn NOT EXISTS" không? Nó có thể rõ ràng, nhưng tôi chưa bao giờ thấy điều đó trong tài liệu. Cảm ơn.
toni07

2
@ toni07 Thực ra, đó là một huyền thoại. LEFT JOIN sẽ thắng. explainextended.com/2009/09/18/... .. blog của Quassnoi luôn là một nguồn tài nguyên hữu ích.
Kaii

làm thế nào tôi sẽ sử dụng điều này trong một mệnh đề HAVING? akagroup by X having exist [row with employeeID = e.id]
phil294

@blauhirn: cứ như vậy
Quassnoi

83
SELECT * FROM employees WHERE name NOT IN (SELECT name FROM eotm_dyn)

HOẶC LÀ

SELECT * FROM employees WHERE NOT EXISTS (SELECT * FROM eotm_dyn WHERE eotm_dyn.name = employees.name)

HOẶC LÀ

SELECT * FROM employees LEFT OUTER JOIN eotm_dyn ON eotm_dyn.name = employees.name WHERE eotm_dyn IS NULL

1
NB! NOT INkhông hoạt động như mong đợi nếu namenullgiá trị. Xem từ 36 phút 20 giây trong video PHẦN: 10 kỹ thuật điều chỉnh truy vấn mà mọi lập trình viên SQL nên biết (Kevin Kline, Aaron Bertrand) .
hlovdal

12

Bạn có thể thực hiện THAM GIA TRÁI và xác nhận cột đã tham gia là NULL.

Thí dụ:

SELECT * FROM employees a LEFT JOIN eotm_dyn b on (a.joinfield=b.joinfield) WHERE b.name IS NULL

7
SELECT * from employees
WHERE NOT EXISTS (SELECT name FROM eotm_dyn)

Không bao giờ trả về bất kỳ bản ghi nào trừ khi eotm_dyntrống. Bạn cần một số loại tiêu chí SELECT name FROM eotm_dynnhư

SELECT * from employees
WHERE NOT EXISTS (
    SELECT name FROM eotm_dyn WHERE eotm_dyn.employeeid = employees.employeeid
)

giả sử rằng hai bảng được liên kết bởi mối quan hệ khóa ngoài. Tại thời điểm này, bạn có thể sử dụng nhiều tùy chọn khác bao gồm THAM GIA TRÁI. Tuy nhiên, trình tối ưu hóa thường sẽ xử lý chúng giống nhau trong hầu hết các trường hợp.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.