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

Làm thế nào để sử dụng ANY thay vì IN trong mệnh đề WHERE với Rails?

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ử idinteger :

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?



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Các cài đặt sẵn có cao của PostgreSQL Patroni

  2. Lỗi Postgres:Nhiều hơn một hàng được trả về bởi một truy vấn con được sử dụng làm biểu thức

  3. Trả lại các hàng từ INSERT với ON CONFLICT mà không cần cập nhật

  4. Django mô hình một khóa ngoại cho nhiều bảng

  5. Cách Atan () hoạt động trong PostgreSQL