Mengabaikan kinerja, apakah saya akan mendapatkan hasil yang sama dari kueri A dan B di bawah ini? Bagaimana dengan C dan D?
-- A
select *
from a left join b
on <blahblah>
left join c
on <blahblan>
-- B
select *
from a left join c
on <blahblah>
left join b
on <blahblan>
-- C
select *
from a join b
on <blahblah>
join c
on <blahblan>
-- D
select *
from a join c
on <blahblah>
join b
on <blahblan>
sql
join
relational-database
Pelajar saja
sumber
sumber
<blahblah>
? apakah Anda bergabung dengan A ke B dan A ke C, atau Anda bergabung dengan A ke B dan B ke C?Jawaban:
Untuk
INNER
bergabung, tidak, urutannya tidak masalah. Kueri akan mengembalikan hasil yang sama, selama Anda mengubah pilihan Anda dariSELECT *
menjadiSELECT a.*, b.*, c.*
.Untuk (
LEFT
,RIGHT
atauFULL
)OUTER
bergabung, ya, urutannya penting - dan ( diperbarui ) jauh lebih rumit.Pertama, sambungan luar tidak komutatif, jadi
a LEFT JOIN b
tidak sama denganb LEFT JOIN a
Gabungan luar juga tidak asosiatif, jadi dalam contoh Anda yang melibatkan properti (komutatif dan asosiatif):
setara dengan :
tapi:
tidak setara dengan :
Contoh asosiatif lain (semoga lebih sederhana). Pikirkan ini sebagai
(a LEFT JOIN b) LEFT JOIN c
:Ini setara dengan
a LEFT JOIN (b LEFT JOIN c)
:hanya karena kami memiliki
ON
kondisi "baik" . KeduanyaON b.ab_id = a.ab_id
dan keduanyac.bc_id = b.bc_id
adalah pemeriksaan kesetaraan dan tidak melibatkanNULL
perbandingan.Anda bahkan dapat memiliki kondisi dengan operator lain atau yang lebih kompleks seperti:
ON a.x <= b.x
atauON a.x = 7
atauON a.x LIKE b.x
danON (a.x, a.y) = (b.x, b.y)
dan dua kueri masih akan setara.Namun, jika salah satu dari ini terlibat
IS NULL
atau fungsi yang terkait dengan nol sepertiCOALESCE()
, misalnya jika kondisinyab.ab_id IS NULL
, maka dua kueri tidak akan setara.sumber
a.somecol > 0 OR b.someothercol > 0
; asosiatif dapat gagal untuk kondisi itu.INNER JOIN
dan berikutLEFT JOIN
. Apakah ini berfungsi seperti itu, pertama permintaan akanFilter
catatan di pangkalanINNER JOIN
dan kemudian akan berlakuLEFT JOIN
untukFiltered
catatan?ON
klausa (yaitu "spesifikasi gabungan") ke lokasi baru . Ini hanya sintaks. Jika Anda menggunakan notasi aljabar relasional (di mana spesifikasi gabungan ditempatkan di bawah operator gabungan), maka asosiatif menjadi lebih jelas. Argumen Anda hanya menampilkan bahwa sambungan luar tidak komutatif , yang benaruntuk Bergabung reguler, tidak.
TableA join TableB
akan menghasilkan rencana eksekusi yang sama denganTableB join TableA
(jadi contoh C dan D Anda akan sama)untuk bergabung kiri dan kanan itu.
TableA left Join TableB
berbeda dariTableB left Join TableA
, TETAPI sama sajaTableB right Join TableA
sumber
Jika Anda mencoba bergabung dengan C pada bidang dari B sebelum bergabung dengan B, yaitu:
permintaan Anda akan gagal, jadi dalam hal ini urutan penting.
sumber
Oracle optimizer memilih gabungan urutan tabel untuk inner join. Pengoptimal memilih urutan gabungan tabel hanya dalam klausa FROM sederhana. Anda dapat memeriksa dokumentasi oracle di situs web mereka. Dan untuk kiri, gabung kanan luar, jawaban yang paling banyak dipilih adalah benar. Pengoptimal memilih urutan gabungan optimal serta indeks optimal untuk setiap tabel. Pesanan gabungan dapat memengaruhi indeks mana yang merupakan pilihan terbaik. Pengoptimal dapat memilih indeks sebagai jalur akses untuk tabel jika itu adalah tabel dalam, tetapi tidak jika itu adalah tabel luar (dan tidak ada kualifikasi lebih lanjut).
Pengoptimal memilih urutan gabungan tabel hanya dalam klausa FROM sederhana. Sebagian besar gabungan yang menggunakan kata kunci JOIN diratakan menjadi gabungan sederhana, sehingga pengoptimal memilih urutan gabungannya.
Pengoptimal tidak memilih urutan gabungan untuk gabungan luar; menggunakan urutan yang ditentukan dalam pernyataan.
Saat memilih pesanan bergabung, pengoptimal memperhitungkan: Ukuran setiap tabel Indeks tersedia pada setiap tabel Apakah indeks pada tabel berguna dalam urutan bergabung tertentu Jumlah baris dan halaman yang akan dipindai untuk setiap tabel di setiap tabel bergabung dalam pesanan
sumber