SQL BERGABUNG dan berbagai jenis GABUNGAN

244

Apa itu SQL JOINdan apa jenisnya?

MD
sumber

Jawaban:

330

Ilustrasi dari W3schools :


INNER JOIN - Hanya catatan yang cocok dengan kondisi di kedua tabel


LEFT JOIN - Semua catatan dari tabel 1 bersamaan dengan catatan yang cocok dengan kondisi di tabel 2


BERGABUNG DENGAN BENAR - Semua catatan dari tabel 2 bersamaan dengan catatan dari tabel 1 yang cocok dengan kondisi


FULL OUTER JOIN - Kombinasi kedua Outer dan Right Outer bergabung dengan klausa ON tetapi mempertahankan kedua tabel


Anup
sumber
27
@KNU The w3fools harus memberikan kredit dari tempat mereka mengambil ide untuk gambar. Lihat Visualisasi SQL bergabung oleh Jeff Atwood (ya, orang yang ikut menulis SO) dan artikel yang ditautkan oleh Ligaya Turmelle di mana Jeff mendapat ide dan mengembangkannya.
ypercubeᵀᴹ
2
@ avi gabung kiri dan kanan serupa, jika Anda tidak terganggu yang merupakan tabel utama bergabung berdasarkan.
Anup
2
@ philipxy: Itu definisi yang aneh (bahkan jika Anda benar). Tapi saya lebih suka berputar dan mulai dengan cross join dan kemudian "build" inner join di atasnya. Lagipula, konsep cross join belaka membuat visualisasi diagram Venn yang informal dan tidak akurat ini ...
Lukas Eder
1
Gambar-gambar ini tampaknya menyiratkan bahwa persatuan sama dengan gabungan luar penuh dan persimpangan sama dengan gabungan dalam yang tidak benar sejauh yang saya tahu.
mightyWOZ
1
@DevDave, karena bertentangan dengan kepercayaan populer - gambar tidak bernilai ribuan kata. Lihat jawaban selanjutnya.
hyankov
248

Apa SQL JOIN?

SQL JOIN adalah metode untuk mengambil data dari dua atau lebih tabel database.

Apa perbedaannya SQL JOIN?

Ada total lima JOINs. Mereka :

  1. JOIN or INNER JOIN
  2. OUTER JOIN

     2.1 LEFT OUTER JOIN or LEFT JOIN
     2.2 RIGHT OUTER JOIN or RIGHT JOIN
     2.3 FULL OUTER JOIN or FULL JOIN

  3. NATURAL JOIN
  4. CROSS JOIN
  5. SELF JOIN

1. GABUNG atau GABUNGAN DALAM:

Dalam jenis a ini JOIN, kami mendapatkan semua catatan yang cocok dengan kondisi di kedua tabel, dan catatan di kedua tabel yang tidak cocok tidak dilaporkan.

Dengan kata lain, INNER JOINdidasarkan pada fakta tunggal bahwa: HANYA entri yang cocok dalam KEDUA tabel HARUS dicantumkan.

Perhatikan bahwa JOINtanpa lainnya JOINkata kunci (seperti INNER, OUTER, LEFT, dll) adalah INNER JOIN. Dengan kata lain, JOINadalah gula sintaksis untuk INNER JOIN(lihat: Perbedaan antara BERGABUNG dan BERGABUNG DALAM ).

2. GABUNG LUAR:

OUTER JOIN mengambil

Entah, baris yang cocok dari satu tabel dan semua baris di tabel lain Atau, semua baris di semua tabel (tidak masalah apakah ada kecocokan atau tidak).

Ada tiga jenis Outer Join:

2.1 BERGABUNG LEFT OUTER atau LEFT JOIN

Gabung ini mengembalikan semua baris dari tabel kiri bersamaan dengan baris yang cocok dari tabel kanan. Jika tidak ada kolom yang cocok di tabel kanan, itu mengembalikan NULLnilai.

2.2 BERGABUNG DENGAN BENAR atau BERGABUNG KANAN

Ini JOINmengembalikan semua baris dari tabel kanan bersamaan dengan baris yang cocok dari tabel kiri. Jika tidak ada kolom yang cocok di tabel sebelah kiri, itu mengembalikan NULLnilai.

2.3 BERGABUNG FULL OUTER atau FULL JOIN

Ini JOINmenggabungkan LEFT OUTER JOINdan RIGHT OUTER JOIN. Ini mengembalikan baris dari tabel mana pun ketika kondisi terpenuhi dan mengembalikan NULLnilai ketika tidak ada kecocokan.

Dengan kata lain, OUTER JOINdidasarkan pada kenyataan bahwa: HANYA entri yang cocok di SALAH SATU tabel (KANAN atau KIRI) atau KEDUA tabel (PENUH) HARUS dicantumkan.

Note that `OUTER JOIN` is a loosened form of `INNER JOIN`.

3. GABUNG ALAMI:

Ini didasarkan pada dua kondisi:

  1. yang JOINdibuat pada semua kolom dengan nama yang sama untuk kesetaraan.
  2. Menghapus kolom duplikat dari hasilnya.

Ini tampaknya lebih bersifat teoritis dan sebagai hasilnya (mungkin) sebagian besar DBMS bahkan tidak repot-repot mendukung ini.

4. LINTAS BERGABUNG:

Ini adalah produk Cartesian dari dua tabel yang terlibat. Hasil dari CROSS JOINtidak akan masuk akal di sebagian besar situasi. Selain itu, kita tidak akan membutuhkan ini sama sekali (atau perlu paling tidak, tepatnya).

5. BERGABUNG DIRI:

Ini bukan bentuk yang berbeda dari JOIN, melainkan merupakan JOIN( INNER, OUTER, dll) dari meja untuk dirinya sendiri.

GABUNG berdasarkan Operator

Bergantung pada operator yang digunakan untuk JOINklausa, mungkin ada dua jenis JOINs. Mereka

  1. Equi GABUNG
  2. Theta BERGABUNG

1. Equi BERGABUNG:

Untuk JOINjenis apa pun ( INNER,, OUTERdll), jika kita HANYA menggunakan operator persamaan (=), maka kita mengatakan bahwa itu JOINadalah EQUI JOIN.

2. Theta BERGABUNG:

Ini sama seperti EQUI JOINtetapi memungkinkan semua operator lain seperti>, <,> = dll.

Banyak yang menganggap keduanya EQUI JOINdan Theta JOINmirip dengan INNER, OUTER dll JOIN. Tapi saya sangat percaya bahwa ini adalah kesalahan dan membuat ide-ide itu kabur. Karena INNER JOIN, OUTER JOINdll semua terhubung dengan tabel dan data mereka sedangkan EQUI JOINdan THETA JOINhanya terhubung dengan operator yang kami gunakan di yang sebelumnya.

Sekali lagi, ada banyak orang yang menganggapnya NATURAL JOINsebagai "aneh" EQUI JOIN. Sebenarnya, itu benar, karena syarat pertama yang saya sebutkan NATURAL JOIN. Namun, kita tidak harus membatasi itu hanya untuk NATURAL JOINs saja. INNER JOINs, OUTER JOINs dll bisa menjadi EQUI JOINterlalu.

MD
sumber
2
Ada LATERAL GABUNG yang relatif baru .. PILIH * DARI r1, LATERAL fx (r1)
Pavel Stehule
13
Meskipun ini tampaknya masuk akal, saya tidak berpikir jawaban "apa itu bergabung SQL" dengan cara apa pun yang menyampaikan informasi yang berguna. Jawabannya secara keseluruhan adalah referensi yang ditulis untuk orang-orang yang sudah mengerti bergabung, bukan untuk orang-orang yang bertanya. Ini juga menghilangkan referensi, baik untuk mendukung klaimnya (sebagaimana yang tepat jika membuat jawaban otoritatif) dan untuk memberikan penjelasan tambahan melalui sumber daya eksternal. Jika Anda mencoba menulis jawaban resmi untuk menautkan pengguna SQL baru, mungkin ada baiknya sedikit mengisi bagian yang kosong, terutama bagian "apa yang bergabung".
Craig Ringer
dapatkah Anda memberikan beberapa contoh?
avi
67

Definisi:


BERGABUNG adalah cara untuk meminta data yang digabungkan bersama dari beberapa tabel secara bersamaan.

Jenis GABUNGAN:


Mengenai RDBMS ada 5 jenis gabungan:

  • Equi-Join: Menggabungkan catatan umum dari dua tabel berdasarkan kondisi kesetaraan. Secara teknis, Gabung dibuat dengan menggunakan operator kesetaraan (=) untuk membandingkan nilai-nilai Kunci Utama dari satu tabel dan nilai-nilai Kunci Asing dari tabel lain, maka set hasil mencakup catatan umum (cocok) dari kedua tabel. Untuk implementasi, lihat INNER-JOIN.

  • Natural-Join: Ini adalah versi yang disempurnakan dari Equi-Join, di mana operasi SELECT menghilangkan kolom duplikat. Untuk implementasi, lihat INNER-JOIN

  • Non-Equi-Join: Ini adalah kebalikan dari Equi-join di mana kondisi bergabung menggunakan selain dari operator yang sama (=) misalnya,! =, <=,> =, BETWEEN dll. Untuk implementasi, lihat INNER-JOIN.

  • Gabung Sendiri:: Perilaku bergabung yang disesuaikan di mana tabel dikombinasikan dengan dirinya sendiri; Ini biasanya diperlukan untuk menanyakan tabel referensi-sendiri (atau entitas hubungan Unary). Untuk implementasi, lihat INNER-JOINs.

  • Produk Cartesian: Ini lintas menggabungkan semua catatan dari kedua tabel tanpa kondisi apa pun. Secara teknis, ini mengembalikan set hasil kueri tanpa WHERE-Clause.

Sehubungan dengan kepedulian dan kemajuan SQL, ada 3 jenis gabungan dan semua gabungan RDBMS dapat dicapai dengan menggunakan jenis gabungan ini.

  1. INNER-JOIN: Menggabungkan (atau menggabungkan) baris yang cocok dari dua tabel. Pencocokan dilakukan berdasarkan kolom umum tabel dan operasi pembandingannya. Jika kondisi berdasarkan kesetaraan maka: EQUI-JOIN dilakukan, jika tidak Non-EQUI-Bergabung.

  2. OUTER-JOIN: Menggabungkan (atau menggabungkan) baris yang cocok dari dua tabel dan baris yang tidak cocok dengan nilai NULL. Namun, dapat mengkustomisasi pemilihan baris yang tidak cocok misalnya, memilih baris yang tidak cocok dari tabel pertama atau tabel kedua berdasarkan sub-tipe: LEFT OUTER JOIN dan RIGHT OUTER JOIN.

    2.1. LEFT Outer JOIN (alias, LEFT-JOIN): Mengembalikan baris yang cocok dari dua tabel dan tidak cocok dengan tabel LEFT (yaitu, tabel pertama).

    2.2. RIGHT Outer JOIN (alias, RIGHT-JOIN): Mengembalikan baris yang cocok dari dua tabel dan tidak cocok dengan tabel RIGHT saja.

    2.3. FULL OUTER JOIN (alias OUTER JOIN): Pengembalian cocok dan tidak cocok dari kedua tabel.

  3. GABUNG-GABUNG: Gabung ini tidak menggabungkan / menggabungkan melainkan melakukan produk Cartesian.

masukkan deskripsi gambar di sini Catatan: Self-JOIN dapat diraih oleh INNER-JOIN, OUTER-JOIN dan CROSS-JOIN berdasarkan persyaratan tetapi tabel harus bergabung dengan dirinya sendiri.

Untuk informasi lebih lanjut:

Contoh:

1.1: INNER-JOIN: Implementasi Equi-join

SELECT  *
FROM Table1 A 
 INNER JOIN Table2 B ON A.<Primary-Key> =B.<Foreign-Key>;

1.2: INNER-JOIN: Implementasi Natural-JOIN

Select A.*, B.Col1, B.Col2          --But no B.ForeignKeyColumn in Select
 FROM Table1 A
 INNER JOIN Table2 B On A.Pk = B.Fk;

1.3: INNER-JOIN dengan implementasi NON-Equi-join

Select *
 FROM Table1 A INNER JOIN Table2 B On A.Pk <= B.Fk;

1.4: INNER-JOIN dengan DIRI-JOIN

Select *
 FROM Table1 A1 INNER JOIN Table1 A2 On A1.Pk = A2.Fk;

2.1: OUTER JOIN (gabung luar penuh)

Select *
 FROM Table1 A FULL OUTER JOIN Table2 B On A.Pk = B.Fk;

2.2: KIRI BERGABUNG

Select *
 FROM Table1 A LEFT OUTER JOIN Table2 B On A.Pk = B.Fk;

2.3: BERGABUNG DENGAN BENAR

Select *
 FROM Table1 A RIGHT OUTER JOIN Table2 B On A.Pk = B.Fk;

3.1: LINTAS BERGABUNG

Select *
 FROM TableA CROSS JOIN TableB;

3.2: CROSS JOIN-Self JOIN

Select *
 FROM Table1 A1 CROSS JOIN Table1 A2;

//ATAU//

Select *
 FROM Table1 A1,Table1 A2;
nayeemDotNetAuthorities
sumber
Label "Tabel 1" & "Tabel 2" & label di bawahnya tidak sesuai, berasal dari ilustrasi intersect/ except/ union; di sini lingkaran adalah baris yang dikembalikan oleh left& right join, seperti yang dikatakan label bernomor. Gambar AXB adalah omong kosong. cross join= inner join on 1=1& adalah kasus khusus dari diagram pertama.
philipxy
Perlu disebutkan SQL-92 mendefinisikan UNION JOIN. Sekarang dibuat usang dalam SQL: 2003.
The Impaler
40

Menariknya, sebagian besar jawaban lain menderita dua masalah ini:

Saya baru-baru ini menulis sebuah artikel tentang topik ini: Sebuah Panduan Komprehensif yang Mungkin Tidak Lengkap untuk Berbagai Cara untuk BERGABUNG Tabel dalam SQL , yang akan saya ringkas di sini.

Pertama dan terpenting: GABUNG adalah produk kartesius

Inilah sebabnya mengapa diagram Venn menjelaskannya secara tidak akurat, karena JOIN membuat produk kartesius di antara dua tabel yang digabungkan. Wikipedia menggambarkannya dengan baik:

masukkan deskripsi gambar di sini

Sintaks SQL untuk produk kartesius adalah CROSS JOIN. Sebagai contoh:

SELECT *

-- This just generates all the days in January 2017
FROM generate_series(
  '2017-01-01'::TIMESTAMP,
  '2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
  INTERVAL '1 day'
) AS days(day)

-- Here, we're combining all days with all departments
CROSS JOIN departments

Yang menggabungkan semua baris dari satu tabel dengan semua baris dari tabel lainnya:

Sumber:

+--------+   +------------+
| day    |   | department |
+--------+   +------------+
| Jan 01 |   | Dept 1     |
| Jan 02 |   | Dept 2     |
| ...    |   | Dept 3     |
| Jan 30 |   +------------+
| Jan 31 |
+--------+

Hasil:

+--------+------------+
| day    | department |
+--------+------------+
| Jan 01 | Dept 1     |
| Jan 01 | Dept 2     |
| Jan 01 | Dept 3     |
| Jan 02 | Dept 1     |
| Jan 02 | Dept 2     |
| Jan 02 | Dept 3     |
| ...    | ...        |
| Jan 31 | Dept 1     |
| Jan 31 | Dept 2     |
| Jan 31 | Dept 3     |
+--------+------------+

Jika kita hanya menulis daftar tabel yang dipisahkan koma, kita akan mendapatkan yang sama:

-- CROSS JOINing two tables:
SELECT * FROM table1, table2

INNER JOIN (Theta-JOIN)

An INNER JOINhanya disaring di CROSS JOINmana predikat filter disebut Thetadalam aljabar relasional.

Misalnya:

SELECT *

-- Same as before
FROM generate_series(
  '2017-01-01'::TIMESTAMP,
  '2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
  INTERVAL '1 day'
) AS days(day)

-- Now, exclude all days/departments combinations for
-- days before the department was created
JOIN departments AS d ON day >= d.created_at

Perhatikan bahwa kata kunci INNERadalah opsional (kecuali dalam MS Access).

( lihat artikel untuk contoh hasil )

EQUI BERGABUNG

Jenis khusus Theta-JOIN adalah equi JOIN, yang paling sering kita gunakan. Predikat bergabung dengan kunci utama dari satu tabel dengan kunci asing dari tabel lain. Jika kita menggunakan database Sakila untuk ilustrasi, kita dapat menulis:

SELECT *
FROM actor AS a
JOIN film_actor AS fa ON a.actor_id = fa.actor_id
JOIN film AS f ON f.film_id = fa.film_id

Ini menggabungkan semua aktor dengan film mereka.

Atau juga, pada beberapa database:

SELECT *
FROM actor
JOIN film_actor USING (actor_id)
JOIN film USING (film_id)

The USING()sintaks memungkinkan untuk menentukan kolom yang harus hadir di kedua sisi dari BERGABUNG meja operasi dan menciptakan predikat kesetaraan pada dua kolom.

GABUNG ALAMI

Jawaban lain telah mencantumkan "tipe GABUNG" ini secara terpisah, tetapi itu tidak masuk akal. Ini hanya bentuk gula sintaksis untuk equi JOIN, yang merupakan kasus khusus dari Theta-JOIN atau INNER JOIN. GABUNG ALAMI hanya mengumpulkan semua kolom yang umum untuk kedua tabel yang bergabung dan bergabung USING()dengan kolom tersebut. Yang hampir tidak pernah berguna, karena kecocokan yang tidak disengaja (seperti LAST_UPDATEkolom dalam database Sakila ).

Inilah sintaksinya:

SELECT *
FROM actor
NATURAL JOIN film_actor
NATURAL JOIN film

OUTER BERGABUNG

Sekarang, OUTER JOINsedikit berbeda dari INNER JOINkarena ia menciptakan UNIONbeberapa produk kartesius. Kita bisa menulis:

-- Convenient syntax:
SELECT *
FROM a LEFT JOIN b ON <predicate>

-- Cumbersome, equivalent syntax:
SELECT a.*, b.*
FROM a JOIN b ON <predicate>
UNION ALL
SELECT a.*, NULL, NULL, ..., NULL
FROM a
WHERE NOT EXISTS (
  SELECT * FROM b WHERE <predicate>
)

Tidak ada yang mau menulis yang terakhir, jadi kami menulis OUTER JOIN(yang biasanya lebih baik dioptimalkan oleh basis data).

Seperti INNER, kata kunci OUTERbersifat opsional, di sini.

OUTER JOIN hadir dalam tiga rasa:

  • LEFT [ OUTER ] JOIN: Tabel kiri JOINungkapan ditambahkan ke gabungan seperti yang ditunjukkan di atas.
  • RIGHT [ OUTER ] JOIN: Tabel kanan JOINungkapan ditambahkan ke serikat seperti yang ditunjukkan di atas.
  • FULL [ OUTER ] JOIN: Kedua tabel JOINekspresi ditambahkan ke gabungan seperti yang ditunjukkan di atas.

Semua ini dapat dikombinasikan dengan kata kunci USING()atau dengan NATURAL( Saya benar-benar memiliki kasus penggunaan dunia nyata untuk NATURAL FULL JOINbaru - baru ini )

Sintaks alternatif

Ada beberapa sintaks historis dan usang di Oracle dan SQL Server, yang OUTER JOINsudah mendukung sebelum standar SQL memiliki sintaks untuk ini:

-- Oracle
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id = fa.actor_id(+)
AND fa.film_id = f.film_id(+)

-- SQL Server
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id *= fa.actor_id
AND fa.film_id *= f.film_id

Karena itu, jangan gunakan sintaks ini. Saya hanya daftar ini di sini sehingga Anda dapat mengenalinya dari posting blog lama / kode warisan.

Dipartisi OUTER JOIN

Beberapa orang tahu ini, tetapi standar SQL menentukan dipartisi OUTER JOIN(dan Oracle mengimplementasikannya). Anda dapat menulis hal-hal seperti ini:

WITH

  -- Using CONNECT BY to generate all dates in January
  days(day) AS (
    SELECT DATE '2017-01-01' + LEVEL - 1
    FROM dual
    CONNECT BY LEVEL <= 31
  ),

  -- Our departments
  departments(department, created_at) AS (
    SELECT 'Dept 1', DATE '2017-01-10' FROM dual UNION ALL
    SELECT 'Dept 2', DATE '2017-01-11' FROM dual UNION ALL
    SELECT 'Dept 3', DATE '2017-01-12' FROM dual UNION ALL
    SELECT 'Dept 4', DATE '2017-04-01' FROM dual UNION ALL
    SELECT 'Dept 5', DATE '2017-04-02' FROM dual
  )
SELECT *
FROM days 
LEFT JOIN departments 
  PARTITION BY (department) -- This is where the magic happens
  ON day >= created_at

Bagian dari hasil:

+--------+------------+------------+
| day    | department | created_at |
+--------+------------+------------+
| Jan 01 | Dept 1     |            | -- Didn't match, but still get row
| Jan 02 | Dept 1     |            | -- Didn't match, but still get row
| ...    | Dept 1     |            | -- Didn't match, but still get row
| Jan 09 | Dept 1     |            | -- Didn't match, but still get row
| Jan 10 | Dept 1     | Jan 10     | -- Matches, so get join result
| Jan 11 | Dept 1     | Jan 10     | -- Matches, so get join result
| Jan 12 | Dept 1     | Jan 10     | -- Matches, so get join result
| ...    | Dept 1     | Jan 10     | -- Matches, so get join result
| Jan 31 | Dept 1     | Jan 10     | -- Matches, so get join result

Intinya di sini adalah bahwa semua baris dari sisi yang dipartisi dari gabungan akan berakhir di hasil terlepas jika JOINcocok dengan apa pun di "sisi lain dari GABUNG". Singkat cerita: Ini untuk mengisi data yang jarang dalam laporan. Sangat berguna!

SEMI BERGABUNG

Serius? Tidak ada jawaban lain yang mengerti? Tentu saja tidak, karena tidak memiliki sintaks asli dalam SQL, sayangnya (seperti ANTI GABUNG di bawah). Tetapi kita dapat menggunakan IN()dan EXISTS(), misalnya untuk menemukan semua aktor yang telah bermain dalam film:

SELECT *
FROM actor a
WHERE EXISTS (
  SELECT * FROM film_actor fa
  WHERE a.actor_id = fa.actor_id
)

The WHERE a.actor_id = fa.actor_idpredikat bertindak sebagai semi bergabung predikat. Jika Anda tidak percaya, periksa rencana eksekusi, misalnya di Oracle. Anda akan melihat bahwa basis data mengeksekusi operasi SEMI GABUNG, bukan EXISTS()predikat.

masukkan deskripsi gambar di sini

ANTI BERGABUNG

Ini adalah kebalikan dari SEMI BERGABUNG ( hati-hati untuk tidak menggunakan NOT INmeskipun , karena memiliki peringatan penting)

Berikut adalah semua aktor tanpa film:

SELECT *
FROM actor a
WHERE NOT EXISTS (
  SELECT * FROM film_actor fa
  WHERE a.actor_id = fa.actor_id
)

Beberapa orang (terutama orang MySQL) juga menulis ANTI JOIN seperti ini:

SELECT *
FROM actor a
LEFT JOIN film_actor fa
USING (actor_id)
WHERE film_id IS NULL

Saya pikir alasan historisnya adalah kinerja.

GABUNGAN LATERAL

OMG, ini terlalu keren. Saya satu-satunya yang menyebutkannya? Inilah pertanyaan keren:

SELECT a.first_name, a.last_name, f.*
FROM actor AS a
LEFT OUTER JOIN LATERAL (
  SELECT f.title, SUM(amount) AS revenue
  FROM film AS f
  JOIN film_actor AS fa USING (film_id)
  JOIN inventory AS i USING (film_id)
  JOIN rental AS r USING (inventory_id)
  JOIN payment AS p USING (rental_id)
  WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!
  GROUP BY f.film_id
  ORDER BY revenue DESC
  LIMIT 5
) AS f
ON true

Ini akan menemukan film TOP 5 penghasil pendapatan per aktor. Setiap kali Anda membutuhkan permintaan TOP-N-per-sesuatu, LATERAL JOINakan menjadi teman Anda. Jika Anda orang SQL Server, maka Anda tahu JOINjenis ini di bawah namaAPPLY

SELECT a.first_name, a.last_name, f.*
FROM actor AS a
OUTER APPLY (
  SELECT f.title, SUM(amount) AS revenue
  FROM film AS f
  JOIN film_actor AS fa ON f.film_id = fa.film_id
  JOIN inventory AS i ON f.film_id = i.film_id
  JOIN rental AS r ON i.inventory_id = r.inventory_id
  JOIN payment AS p ON r.rental_id = p.rental_id
  WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!
  GROUP BY f.film_id
  ORDER BY revenue DESC
  LIMIT 5
) AS f

OK, mungkin itu curang, karena a LATERAL JOINatau APPLYekspresi benar-benar "subquery berkorelasi" yang menghasilkan beberapa baris. Tetapi jika kita mengizinkan "subqueries berkorelasi", kita juga dapat berbicara tentang ...

MULTISET

Ini hanya benar-benar diimplementasikan oleh Oracle dan Informix (setahu saya), tetapi dapat ditiru dalam PostgreSQL menggunakan array dan / atau XML dan di SQL Server menggunakan XML.

MULTISETmenghasilkan subquery yang berkorelasi dan menghasilkan kumpulan baris yang dihasilkan di kueri luar. Kueri di bawah ini memilih semua aktor dan untuk setiap aktor mengumpulkan film mereka dalam koleksi bersarang:

SELECT a.*, MULTISET (
  SELECT f.*
  FROM film AS f
  JOIN film_actor AS fa USING (film_id)
  WHERE a.actor_id = fa.actor_id
) AS films
FROM actor

Seperti yang Anda lihat, ada lebih banyak jenis BERGABUNG dari sekedar "membosankan" INNER, OUTERdan CROSS JOINyang biasanya disebutkan. Lebih detail di artikel saya . Dan tolong, berhenti menggunakan diagram Venn untuk mengilustrasikannya.

Lukas Eder
sumber
Equijoin adalah kasus khusus dari theta-join di mana theta adalah kesetaraan. Theta-join adalah analog dengan kasus khusus dari join dalam di mana on adalah perbandingan theta pada kolom dari masing-masing. Beberapa dekade setelah Codd mendefinisikan mereka beberapa buku teks salah mendefinisikan theta join sebagai generalisasi yang merupakan analog dari inner join.
philipxy
@ philipxy: Ada yang spesifik yang harus saya ubah dalam jawaban saya? Anda dapat menyarankan hasil edit ...
Lukas Eder
10

Saya telah membuat ilustrasi yang menjelaskan lebih baik daripada kata-kata, menurut saya: SQL Bergabung dengan tabel penjelasan

Gisway
sumber
@Niraj Lingkaran A & B tidak mengandung baris A & B. Mereka disalin secara membabi buta dari tempat lain tanpa kredit. Gabung silang termasuk dalam kasus gabung dalam, itu gabung dalam pada 1 = 1. Dengan cara apa bagian-bagian gambar ini "sempurna"?
philipxy
@ philipxy Maaf tapi saya tidak terganggu jika disalin dari tempat lain. dan saya tidak yakin mana yang tidak benar pada gambar di atas. bagi saya ini tidak masalah. Gabung silang tidak dijelaskan di sini. Itu tidak termasuk dalam gabungan batin ..
Niraj
-3

Saya akan mendorong hewan peliharaan saya kesal: kata kunci PENGGUNAAN.

Jika kedua tabel di kedua sisi GABUNG memiliki kunci asing dengan benar dinamai (yaitu, nama yang sama, bukan hanya "id) maka ini dapat digunakan:

SELECT ...
FROM customers JOIN orders USING (customer_id)

Saya menemukan ini sangat praktis, mudah dibaca, dan tidak cukup sering digunakan.

peufeu
sumber
2
Ini tidak menjawab pertanyaan. Itu milik sebagai komentar baik di bawah pertanyaan atau salah satu jawaban.
TylerH