Ini berfungsi:
SELECT *
FROM element
WHERE (pk1, pk2, pk3) IN (SELECT (unnest(elements)).*
FROM collection
WHERE id = 1);
Atau lebih bertele-tele, tetapi lebih disukai :
SELECT *
FROM element
WHERE (pk1, pk2, pk3) IN (SELECT (e).*
FROM collection c, unnest(c.elements) e
WHERE c.id = 1);
Lebih kuat dan menghindari evaluasi unnest()
beberapa kali. Lihat:
Ini juga berfungsi:
SELECT *
FROM element
WHERE ROW((pk1, pk2, pk3)) IN (SELECT unnest(elements)
FROM collection
WHERE id = 1);
Inti masalahnya adalah IN
mengambil subkueri mengetahui dua bentuk yang terpisah. Mengutip manual:
Kueri Anda yang gagal memutuskan ke bentuk kedua, sementara Anda (dapat dimengerti) mengharapkan yang pertama. Tapi bentuk kedua melakukan ini:
Kueri pertama dan kedua . saya membuatnya bekerja dengan mengurai jenis baris
di sebelah kanan operator. Jadi Postgres memiliki tiga bigint
nilai kiri dan kanan dan puas.
Kueri ketiga My saya membuatnya bekerja dengan menyarangkan jenis baris ke kiri di konstruktor baris . Postgres hanya menguraikan level pertama dan berakhir dengan satu tipe komposit - mencocokkan tipe komposit tunggal di sebelah kanan.
Perhatikan bahwa kata kunci ROW
diperlukan untuk satu bidang yang kita bungkus. Manual:
Kueri kerja Anda agak berbeda karena menyediakan daftar nilai di sebelah kanan alih-alih subquery (setel ). Itu implementasi yang berbeda mengambil jalur kode yang berbeda. Bahkan mendapat bab terpisah dalam manual . Varian ini tidak memiliki perlakuan khusus untuk konstruktor ROW ke kiri. Jadi itu hanya berfungsi seperti yang diharapkan (oleh Anda).
Varian sintaks yang lebih setara (berfungsi) dengan = 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[]);
Juga valid dengan (pk1, pk2, pk3)::element_pk_t
atau ROW(pk1, pk2, pk3)::element_pk_t
Lihat:
Karena sumber Anda adalah array , kueri kedua Daniel dengan (e.pk1, e.pk2, e.pk3) = ANY(c.elements)
cocok secara alami.
Tapi untuk bertaruh pada kueri tercepat , uang saya ada di varian kedua, karena saya berharap bisa menggunakan indeks PK secara optimal.
Hanya sebagai bukti konsep. Seperti komentar a_horse:desain DB yang dinormalisasi mungkin akan berskala terbaik.