Đ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.