Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

SQL chọn nơi không có trong truy vấn con không trả về kết quả

Cập nhật:

Các bài viết này trong blog của tôi mô tả sự khác biệt giữa các phương pháp một cách chi tiết hơn:

  • NOT IN so với NOT EXISTS so với LEFT JOIN / IS NULL :SQL Server
  • NOT IN so với NOT EXISTS so với LEFT JOIN / IS NULL :PostgreSQL
  • NOT IN so với NOT EXISTS so với LEFT JOIN / IS NULL :Oracle
  • NOT IN so với NOT EXISTS so với LEFT JOIN / IS NULL :MySQL

Có ba cách để thực hiện một truy vấn như vậy:

  • LEFT JOIN / IS NULL :

    SELECT  *
    FROM    common
    LEFT JOIN
            table1 t1
    ON      t1.common_id = common.common_id
    WHERE   t1.common_id IS NULL
    
  • NOT EXISTS :

    SELECT  *
    FROM    common
    WHERE   NOT EXISTS
            (
            SELECT  NULL
            FROM    table1 t1
            WHERE   t1.common_id = common.common_id
            )
    
  • NOT IN :

    SELECT  *
    FROM    common
    WHERE   common_id NOT IN
            (
            SELECT  common_id
            FROM    table1 t1
            )
    

Khi table1.common_id không thể nullable, tất cả các truy vấn này đều giống nhau về mặt ngữ nghĩa.

Khi nó là nullable, NOT IN khác, vì IN (và do đó, NOT IN ) trả về NULL khi một giá trị không khớp với bất kỳ thứ gì trong danh sách chứa NULL .

Điều này có thể khó hiểu nhưng có thể trở nên rõ ràng hơn nếu chúng ta nhớ lại cú pháp thay thế cho điều này:

common_id = ANY
(
SELECT  common_id
FROM    table1 t1
)

Kết quả của điều kiện này là một sản phẩm boolean của tất cả các phép so sánh trong danh sách. Tất nhiên, một NULL giá trị mang lại NULL kết quả hiển thị toàn bộ kết quả NULL quá.

Chúng tôi không bao giờ có thể chắc chắn rằng common_id không bằng bất kỳ giá trị nào từ danh sách này, vì ít nhất một trong các giá trị là NULL .

Giả sử chúng ta có những dữ liệu này:

common

--
1
3

table1

--
NULL
1
2

LEFT JOIN / IS NULLNOT EXISTS sẽ trả về 3 , NOT IN sẽ trả lại không có gì (vì nó sẽ luôn đánh giá thành FALSE hoặc NULL ).

Trong MySQL , trong trường hợp trên cột không thể nullable, LEFT JOIN / IS NULLNOT IN hiệu quả hơn một chút (vài phần trăm) so với NOT EXISTS . Nếu cột có giá trị rỗng, NOT EXISTS là hiệu quả nhất (một lần nữa, không nhiều).

Trong Oracle , cả ba truy vấn đều mang lại các kế hoạch giống nhau (ANTI JOIN ).

Trong SQL Server , NOT IN / NOT EXISTS hiệu quả hơn, vì LEFT JOIN / IS NULL không thể được tối ưu hóa thành ANTI JOIN bằng trình tối ưu hóa của nó.

Trong PostgreSQL , LEFT JOIN / IS NULLNOT EXISTS hiệu quả hơn NOT IN , sine chúng được tối ưu hóa thành Anti Join , trong khi NOT IN sử dụng hashed subplan (hoặc thậm chí là một subplan đơn giản nếu truy vấn con quá lớn để băm)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Thay đổi mức độ ưu tiên của tài khoản trong cấu hình thư cơ sở dữ liệu (SSMS)

  2. Làm cách nào để truy xuất các bản ghi trong 30 phút qua trong MS SQL?

  3. SQL - Trừ một giá trị cạn kiệt khỏi các hàng

  4. Tính toán khoảng cách giữa hai điểm (Vĩ độ, Kinh độ)

  5. Khắc phục sự cố khi làm việc với ngày và giờ trong SQL Server