Sejak Postgres keluar dengan kemampuan untuk LATERAL
bergabung, saya telah membacanya, karena saat ini saya melakukan dump data yang kompleks untuk tim saya dengan banyak subquery yang tidak efisien yang membuat keseluruhan permintaan membutuhkan waktu empat menit atau lebih.
Saya mengerti bahwa LATERAL
bergabung mungkin dapat membantu saya, tetapi bahkan setelah membaca artikel seperti ini dari Heap Analytics, saya masih belum cukup mengikuti.
Apa kasus penggunaan untuk LATERAL
bergabung? Apa perbedaan antara LATERAL
bergabung dan subquery?
sql
postgresql
subquery
lateral-join
jdotjdot
sumber
sumber
apply
sama denganlateral
dari standar SQL)Jawaban:
Lebih mirip subquery yang berkorelasi
Sebuah
LATERAL
bergabung (Postgres 9.3 atau yang lebih baru) lebih seperti subquery berkorelasi , bukan subquery polos. Seperti yang ditunjukkan Andomar , fungsi atau subquery di sebelah kananLATERAL
join harus dievaluasi satu kali untuk setiap baris di sebelah kiri - sama seperti subquery yang dikorelasikan - sementara subquery polos (ekspresi tabel) dievaluasi sekali saja. (Perencana permintaan memiliki cara untuk mengoptimalkan kinerja untuk keduanya.)Jawaban terkait ini memiliki contoh kode untuk kedua sisi, menyelesaikan masalah yang sama:
Untuk mengembalikan lebih dari satu kolom ,
LATERAL
gabungan biasanya lebih sederhana, lebih bersih, dan lebih cepat.Juga, ingat bahwa padanan subquery yang berkorelasi adalah
LEFT JOIN LATERAL ... ON true
:Baca manual di
LATERAL
Itu lebih berwibawa daripada apa pun yang akan kita jawab di sini:
Hal-hal yang tidak dapat dilakukan subquery
Ada hal - hal yang
LATERAL
bisa dilakukan gabungan, tetapi subquery (berkorelasi) tidak bisa (dengan mudah). Subquery yang dikorelasikan hanya dapat mengembalikan nilai tunggal, bukan beberapa kolom dan bukan beberapa baris - dengan pengecualian panggilan fungsi kosong (yang mengalikan baris hasil jika menghasilkan banyak baris). Tetapi bahkan fungsi set-return tertentu hanya diperbolehkan dalamFROM
klausa. Sukaunnest()
dengan banyak parameter di Postgres 9.4 atau lebih tinggi. Manual:Jadi ini berfungsi, tetapi tidak dapat dengan mudah diganti dengan subquery:
Koma (
,
) dalamFROM
klausa adalah notasi pendek untukCROSS JOIN
.LATERAL
diasumsikan secara otomatis untuk fungsi tabel.Lebih lanjut tentang kasus khusus
UNNEST( array_expression [, ... ] )
:Atur fungsi pengembalian dalam
SELECT
daftarAnda juga dapat menggunakan fungsi set-return seperti
unnest()
dalamSELECT
daftar secara langsung. Ini digunakan untuk memperlihatkan perilaku mengejutkan dengan lebih dari satu fungsi seperti itu dalamSELECT
daftar yang sama hingga Postgres 9.6. Tetapi akhirnya telah disanitasi dengan Postgres 10 dan merupakan alternatif yang valid sekarang (bahkan jika bukan SQL standar). Lihat:Membangun contoh di atas:
Perbandingan:
dbfiddle untuk hal 9.6 di sini
dbfiddle untuk hal 10 di sini
Jelaskan informasi yang salah
Manual:
Jadi dua pertanyaan ini valid (bahkan jika tidak terlalu berguna):
Sementara yang ini tidak:
Itu sebabnya @ Andomar ini contoh kode benar (yang
CROSS JOIN
tidak memerlukan kondisi join) dan @ Attila iniyaitutidak sah.sumber
LATERAL
subquery: gis.stackexchange.com/a/230070/7244Perbedaan antara non-
lateral
danlateral
gabungan terletak pada apakah Anda dapat melihat ke baris tabel sebelah kiri. Sebagai contoh:"Pandangan ke luar" ini berarti bahwa subquery harus dievaluasi lebih dari satu kali. Lagi pula,
t1.col1
dapat mengasumsikan banyak nilai.Sebaliknya, subquery setelah non-
lateral
join dapat dievaluasi sekali:Seperti yang diperlukan tanpa
lateral
, permintaan dalam tidak tergantung dengan cara apa pun pada permintaan luar. Sebuahlateral
permintaan adalah contoh daricorrelated
query, karena hubungannya dengan baris di luar permintaan itu sendiri.sumber
select * from table1 left join t2 using (col1)
membandingkan? Tidak jelas bagi saya ketika bergabung menggunakan / pada kondisi tidak cukup dan akan lebih masuk akal untuk menggunakan lateral.Pertama, Lateral dan Cross Apply adalah hal yang sama . Karena itu, Anda juga dapat membaca tentang Lintas Aplikasi. Karena ini diimplementasikan dalam SQL Server selama berabad-abad, Anda akan menemukan informasi lebih lanjut tentang itu kemudian Lateral.
Kedua, menurut pemahaman saya , tidak ada yang tidak bisa Anda lakukan menggunakan subquery daripada menggunakan lateral. Tapi:
Pertimbangkan permintaan berikut.
Anda dapat menggunakan lateral dalam kondisi ini.
Dalam kueri ini, Anda tidak dapat menggunakan gabungan normal, karena membatasi klausa. Lateral atau Cross Apply dapat digunakan ketika tidak ada kondisi gabung yang sederhana .
Ada lebih banyak penggunaan untuk menerapkan lateral atau lintas tetapi ini adalah yang paling umum yang saya temukan.
sumber
lateral
bukanapply
. Mungkin Microsoft mematenkan sintaks?lateral
dalam standar SQL tetapiapply
tidak.LEFT JOIN
memerlukan kondisi join. Buat ituON TRUE
kecuali Anda ingin membatasi entah bagaimana.cross join
atau suatuon
kondisiSatu hal yang tidak ada yang menunjukkan adalah Anda dapat menggunakan
LATERAL
kueri untuk menerapkan fungsi yang ditentukan pengguna di setiap baris yang dipilih.Misalnya:
Itulah satu-satunya cara saya tahu bagaimana melakukan hal semacam ini di PostgreSQL.
sumber