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

Pisahkan catatan yang dikembalikan fungsi menjadi beberapa kolom

Di Postgres 9.3 atau lebih baru ini paling baik diselesaikan dengan LATERAL bergabung:

SELECT *
FROM   actors a 
JOIN   movies_actors ma on a.actor_id = ma.movie_id 
LEFT   JOIN LATERAL hi_lo(a.actor_id, length(a.name), ma.movie_id) x ON true
LIMIT  10;

Menghindari evaluasi fungsi yang berulang (untuk setiap kolom dalam output - fungsi memang harus dipanggil untuk setiap baris input dengan cara apa pun).
LEFT JOIN LATERAL ... ON true untuk menghindari menjatuhkan baris dari sisi kiri jika fungsi tidak mengembalikan baris:

  • Apa perbedaan antara LATERAL dan subquery di PostgreSQL?

Tindak lanjuti dalam komentar Anda:

hanya kolom yang diperluas yang dihasilkan oleh pemanggilan fungsi

SELECT x.*  -- that's all!
FROM   actors a 
JOIN   movies_actors ma on a.actor_id = ma.movie_id 
LEFT   JOIN LATERAL hi_lo(a.actor_id, length(a.name), ma.movie_id) x ON true
LIMIT  10;

Namun karena Anda tidak peduli dengan kolom lain, Anda dapat menyederhanakannya menjadi:

SELECT x.*
FROM   actors a 
JOIN   movies_actors ma on a.actor_id = ma.movie_id 
     , hi_lo(a.actor_id, length(a.name), ma.movie_id) x
LIMIT  10;

Yang merupakan implisit CROSS JOIN LATERAL . Jika fungsi benar-benar dapat mengembalikan "tidak ada baris" sesekali, hasilnya bisa berbeda:kami tidak mendapatkan nilai NULL untuk baris, baris tersebut hanya dihilangkan - dan LIMIT tidak menghitungnya lagi.

Di versi lama (atau umumnya) Anda juga dapat menguraikan tipe komposit dengan sintaks yang tepat:

SELECT *, (hi_lo(a.actor_id, length(a.name), ma.movie_id)).*  -- note extra parentheses!
FROM   actors a 
JOIN   movies_actors ma on a.actor_id = ma.movie_id 
LIMIT  10;

Kekurangannya adalah bahwa fungsi dievaluasi sekali untuk setiap kolom dalam output fungsi karena kelemahan dalam perencana kueri Postgres. Lebih baik memindahkan panggilan ke subquery atau CTE dan menguraikan jenis baris di SELECT luar . Seperti:

SELECT actor_id, movie_id, (x).*  -- explicit column names for the rest
FROM  (
   SELECT *, hi_lo(a.actor_id, length(a.name), ma.movie_id) AS x
   FROM   actors a 
   JOIN   movies_actors ma on a.actor_id = ma.movie_id 
   LIMIT  10
   ) sub;

Tetapi Anda harus memberi nama masing-masing kolom dan tidak dapat lolos dengan SELECT * kecuali jika Anda setuju dengan jenis baris dalam hasil secara berlebihan. Terkait:

  • Hindari beberapa panggilan pada fungsi yang sama saat memperluas hasil gabungan
  • Bagaimana cara menghindari beberapa evaluasi fungsi dengan sintaks (func()).* dalam kueri SQL?



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Temukan Induk secara Rekursif menggunakan Query

  2. Target waktu pemulihan pgbackrest

  3. Format Angka dengan Koma di PostgreSQL

  4. Cara mengatur nilai bidang variabel komposit menggunakan SQL dinamis

  5. perbarui kueri dengan bergabung di dua tabel