PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Bagaimana cara mencocokkan elemen dalam array tipe komposit?

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.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana cara mengembalikan beberapa baris dari fungsi PL/pgSQL?

  2. PostgreSQL - pg_config -bash:pg_config:perintah tidak ditemukan

  3. Python postgreSQL sqlalchemy meminta kolom DATERANGE

  4. PostgreSQL 13:BATAS ... DENGAN DIKAT

  5. Django ORM meninggalkan koneksi idle di Postgres DB