Có hai biến thể của IN
biểu thức:
-
expression IN (subquery)
-
expression IN (value [, ...])
Tương tự, hai biến thể với ANY
cấu tạo:
- Toán tử biểu thức
-
expression operator ANY (subquery)
Toán tử biểu thức -
expression operator ANY (array expression)
Truy vấn con hoạt động cho một trong hai kỹ thuật, nhưng cho kỹ thuật thứ hai mỗi dạng, IN
mong đợi một danh sách các giá trị (như được định nghĩa trong SQL chuẩn) trong khi = ANY
mong đợi một mảng .
Sử dụng cái nào?
ANY
là một phép bổ sung sau này, linh hoạt hơn, nó có thể được kết hợp với bất kỳ toán tử nhị phân nào trả về giá trị boolean. IN
ghi vào trường hợp đặc biệt của ANY
. Trên thực tế, biểu mẫu thứ hai của nó được viết lại trong nội bộ:
IN
được viết lại bằng = ANY
NOT IN
được viết lại bằng <> ALL
Kiểm tra EXPLAIN
đầu ra cho bất kỳ truy vấn nào để bạn tự xem. Điều này chứng tỏ hai điều:
-
IN
không bao giờ có thể nhanh hơn= ANY
. -
= ANY
về cơ bản sẽ không nhanh hơn đáng kể.
Sự lựa chọn nên được quyết định bởi điều gì dễ cung cấp hơn :danh sách các giá trị hoặc một mảng (có thể là mảng chữ - một giá trị duy nhất).
Nếu các ID bạn sắp chuyển đến từ bên trong DB dù sao, sẽ hiệu quả hơn nhiều nếu chọn chúng trực tiếp (truy vấn con) hoặc tích hợp bảng nguồn vào truy vấn bằng JOIN
(như @mu đã bình luận).
Để vượt qua một danh sách dài các giá trị từ khách hàng của bạn và nhận được hiệu suất tốt nhất , sử dụng một mảng, unnest()
và tham gia hoặc cung cấp nó dưới dạng biểu thức bảng bằng cách sử dụng VALUES
(như @PinnyM đã bình luận). Nhưng lưu ý rằng một JOIN
bảo tồn có thể trùng lặp trong mảng / tập hợp được cung cấp trong khi IN
hoặc = ANY
đừng. Thêm:
- Tối ưu hóa truy vấn Postgres với IN lớn
Khi có giá trị NULL, NOT IN
thường là lựa chọn sai và NOT EXISTS
sẽ đúng (và nhanh hơn nữa):
- Chọn các hàng không có trong bảng khác
Cú pháp cho = ANY
Đối với biểu thức mảng Postgres chấp nhận:
- một phương thức tạo mảng (mảng được tạo từ danh sách các giá trị ở phía Postgres) có dạng:
ARRAY[1,2,3]
- hoặc một ký tự mảng có dạng
'{1,2,3}'
.
Để tránh truyền kiểu không hợp lệ, bạn có thể truyền một cách rõ ràng:
ARRAY[1,2,3]::numeric[]
'{1,2,3}'::bigint[]
Có liên quan:
- PostgreSQL:Vấn đề với việc chuyển mảng sang thủ tục
- Cách chuyển mảng kiểu tùy chỉnh vào hàm Postgres
Hoặc bạn có thể tạo một hàm Postgres lấy VARIADIC
tham số, nhận các đối số riêng lẻ và tạo thành một mảng từ chúng:
- Truyền nhiều giá trị trong một tham số duy nhất
Làm cách nào để chuyển mảng từ Ruby?
Giả sử id
là integer
:
MyModel.where('id = ANY(ARRAY[?]::int[])', ids.map { |i| i})
Nhưng tôi chỉ đang tìm hiểu về Ruby. @mu cung cấp hướng dẫn chi tiết trong câu trả lời liên quan này:
- Gửi mảng giá trị tới truy vấn sql bằng ruby?