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

Làm thế nào để so khớp các phần tử trong một mảng kiểu kết hợp?

Điều này hoạt động:

SELECT *
FROM   element 
WHERE  (pk1, pk2, pk3) IN (SELECT (unnest(elements)).*
                           FROM   collection
                           WHERE  id = 1);

Hoặc dài dòng hơn, nhưng thích hợp hơn :

SELECT *
FROM   element 
WHERE  (pk1, pk2, pk3) IN (SELECT (e).*
                           FROM   collection c, unnest(c.elements) e
                           WHERE  c.id = 1);

Mạnh mẽ hơn và tránh đánh giá unnest() nhiều lần. Xem:

Điều này cũng hoạt động:

SELECT *
FROM   element 
WHERE  ROW((pk1, pk2, pk3)) IN (SELECT unnest(elements)
                                FROM   collection
                                WHERE  id = 1);

Cốt lõi của vấn đề là IN lấy một truy vấn con biết hai dạng riêng biệt. Trích dẫn hướng dẫn:

Truy vấn không thành công của bạn giải quyết ở dạng thứ hai, trong khi bạn (có thể hiểu được) mong đợi dạng đầu tiên. Nhưng hình thức thứ hai thực hiện điều này:

Truy vấn đầu tiên và thứ hai của tôi làm cho nó hoạt động bằng cách phân tách loại hàng ở bên phải của người điều hành. Vì vậy, Postgres có ba bigint giá trị bên trái và bên phải và được thỏa mãn.

Truy vấn thứ ba của tôi làm cho nó hoạt động bằng cách lồng loại hàng ở bên trái trong một hàm tạo hàng . Postgres chỉ phân tách cấp độ đầu tiên và kết thúc bằng một loại kết hợp duy nhất - khớp với loại kết hợp duy nhất ở bên phải.

Lưu ý rằng từ khóa ROW là bắt buộc đối với trường duy nhất mà chúng tôi đang gói. Hướng dẫn sử dụng:

Truy vấn làm việc của bạn khác biệt một cách tinh tế vì nó cung cấp một danh sách các giá trị ở bên phải thay vì truy vấn con ( bộ ). Đó là một cách triển khai khác với một đường dẫn mã khác. Nó thậm chí còn nhận được một chương riêng biệt trong sách hướng dẫn . Biến thể này không có cách xử lý đặc biệt nào cho hàm tạo ROW ở bên trái. Vì vậy, nó chỉ hoạt động như mong đợi (của bạn).

Các biến thể cú pháp tương đương (hoạt động) khác với = ANY :

SELECT * FROM element 
WHERE (pk1, pk2, pk3) = ANY ('{"(1,2,3)","(2,3,4)"}'::element_pk_t[]);

SELECT * FROM element 
WHERE (pk1, pk2, pk3) = ANY (ARRAY[(1,2,3)::element_pk_t,(2,3,4)::element_pk_t]);

SELECT * FROM element 
WHERE (pk1, pk2, pk3) = ANY (ARRAY[(1,2,3),(2,3,4)]::element[]);

Cũng hợp lệ với (pk1, pk2, pk3)::element_pk_t hoặc ROW(pk1, pk2, pk3)::element_pk_t

Xem:

Vì nguồn của bạn là một mảng , Truy vấn thứ hai của Daniel với (e.pk1, e.pk2, e.pk3) = ANY(c.elements) cho vay một cách tự nhiên.
Nhưng để đặt cược vào truy vấn nhanh nhất , tiền của tôi đang ở biến thể thứ hai, bởi vì tôi hy vọng nó sẽ sử dụng chỉ số PK một cách tối ưu.

Cũng như bằng chứng về khái niệm. Giống như a_horse đã nhận xét:một thiết kế DB chuẩn hóa có thể sẽ mở rộng quy mô tốt nhất.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Khung thực thể Cốt lõi postgresql Ánh xạ loại mảng không hoạt động

  2. Lỗi:Bạn phải cài đặt ít nhất một gói postgresql-client- <version>

  3. Cách bảo mật cơ sở dữ liệu PostgreSQL của bạn - 10 mẹo

  4. Kết hợp 2 truy vấn CHỌN

  5. Đã đăng nhập với tư cách là người đăng bài nhưng gặp lỗi người tạo:tạo vai trò mới không thành công:LỖI:phải là người dùng siêu mới để tạo người dùng cấp cao