Toán tử IN so với BẤT KỲ trong PostgreSQL


119

Sự khác biệt giữa toán tử INANYtrong PostgreSQL là gì?
Cơ chế hoạt động của cả hai dường như giống nhau. Bất cứ ai có thể giải thích điều này với một ví dụ?


3
Bản sao có thể có của postgreSQL - trong so với bất kỳ
Vivek S.

Điều này có trả lời câu hỏi của bạn không? Sự khác biệt giữa in và bất kỳ toán tử nào trong sql
philipxy

Câu trả lời:


158

(Không INphải ANYlà "toán tử". Một "cấu trúc" hoặc "phần tử cú pháp".)

Về mặt logic , trích dẫn sách hướng dẫn :

INtương đương với = ANY.

Nhưng có hai biến thể cú pháp của INvà hai biến thể của ANY. Chi tiết:

IN lấy một bộ tương đương với = ANYlấy một bộ , như được minh họa ở đây:

Nhưng biến thể thứ hai của mỗi biến thể không tương đương với biến thể khác. Biến thể thứ hai của ANYcấu trúc nhận một mảng (phải là một kiểu mảng thực tế), trong khi biến thể thứ hai INnhận danh sách các giá trị được phân tách bằng dấu phẩy . Điều này dẫn đến các hạn chế khác nhau trong việc chuyển các giá trị và cũng có thể dẫn đến các kế hoạch truy vấn khác nhau trong các trường hợp đặc biệt:

ANY linh hoạt hơn

Cấu ANYtrúc này linh hoạt hơn nhiều, vì nó có thể được kết hợp với nhiều toán tử khác nhau, không chỉ =. Thí dụ:

SELECT 'foo' LIKE ANY('{FOO,bar,%oo%}');

Đối với một số lượng lớn giá trị, việc cung cấp một bộ quy mô tốt hơn cho từng:

Có liên quan:

Đảo ngược / đối lập / loại trừ

"Tìm các hàng có idtrong mảng đã cho":

SELECT * FROM tbl WHERE id = ANY (ARRAY[1, 2]);

Inversion: "Tìm hàng nơi idkhông trong mảng":

SELECT * FROM tbl WHERE id <> ALL (ARRAY[1, 2]);
SELECT * FROM tbl WHERE id <> ALL ('{1, 2}');  -- equivalent array literal
SELECT * FROM tbl WHERE NOT (id = ANY ('{1, 2}'));

Cả ba tương đương. Cái đầu tiên với hàm tạo mảng , hai cái còn lại với mảng ký tự . Kiểu dữ liệu có thể được lấy từ ngữ cảnh một cách rõ ràng. Ngoài ra, có thể yêu cầu một dàn diễn viên rõ ràng, như'{1,2}'::int[] .

Các hàng với id IS NULLkhông vượt qua một trong hai biểu thức này. Để bao gồm NULLcác giá trị bổ sung:

SELECT * FROM tbl WHERE (id = ANY ('{1, 2}')) IS NOT TRUE;

4
Rất vui được làm rõ một cách rõ ràng rằng kết quả của các biến thể thứ hai sẽ luôn giống nhau. Tôi chắc chắn 99% đó là trường hợp thực tế nhưng câu trả lời dường như không nói rõ điều đó. Có nghĩa là điều đó SELECT * from mytable where id in (1, 2, 3)sẽ luôn dẫn đến các hàng giống nhau SELECT * from mytable where id = ANY('{1, 2, 3}'), ngay cả khi chúng có khả năng có các kế hoạch truy vấn khác nhau.
KPD

1
ANY không thể kết hợp với !=toán tử. Tôi không nghĩ rằng nó được ghi lại bằng tài liệu, nhưng select * from foo where id != ANY (ARRAY[1, 2])không giống với select * from foo where id NOT IN (1, 2). Mặt khác, select * from foo where NOT (id = ANY (ARRAY[1, 2]))hoạt động như mong đợi.
qris

1
@qris: ANYcó thể kết hợp với !=toán tử. Nhưng còn nhiều thứ hơn thế nữa. Tôi đã thêm một chương ở trên. (Lưu ý rằng <>là các nhà điều hành trong SQL chuẩn - mặc dù !=. Được chấp nhận cũng trong Postgres)
Erwin Brandstetter

Phiên bản cuối cùng bao gồm NULLcác giá trị hoạt động như thế nào? Sẽ WHERE id = ANY (ARRAY[1, 2]) OR id IS NULL;hoạt động tốt?
dvtan

1
@dvtan: (id = ...) IS NOT TRUEhoạt động vì id = ...chỉ đánh giá TRUExem có khớp thực tế hay không. Kết quả FALSEhoặc NULLvượt qua bài kiểm tra của chúng tôi. Xem: stackoverflow.com/a/23767625/939860 . Các bài kiểm tra biểu thức đã thêm của bạn cho một thứ khác. Điều này sẽ tương đươngWHERE id <> ALL (ARRAY[1, 2]) OR id IS NULL;
Erwin Brandstetter

3

Có hai điểm rõ ràng, cũng như các điểm trong câu trả lời khác:

  • Chúng hoàn toàn tương đương khi sử dụng các truy vấn phụ:

    SELECT * FROM table
    WHERE column IN(subquery);
    
    SELECT * FROM table
    WHERE column = ANY(subquery);

Mặt khác:

  • Chỉ INtoán tử cho phép một danh sách đơn giản:

    SELECT * FROM table
    WHERE column IN(… ,  , …);

Việc cho rằng chúng hoàn toàn giống nhau đã khiến tôi không khỏi ngạc nhiên khi quên rằng điều ANYđó không hoạt động với danh sách.

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.