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?