Jawaban:
SQL JOIN
?SQL JOIN
adalah metode untuk mengambil data dari dua atau lebih tabel database.
SQL JOIN
?Ada total lima JOIN
s. 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
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 JOIN
didasarkan pada fakta tunggal bahwa: HANYA entri yang cocok dalam KEDUA tabel HARUS dicantumkan.
Perhatikan bahwa JOIN
tanpa lainnya JOIN
kata kunci (seperti INNER
, OUTER
, LEFT
, dll) adalah INNER JOIN
. Dengan kata lain, JOIN
adalah gula sintaksis untuk INNER JOIN
(lihat: Perbedaan antara BERGABUNG dan BERGABUNG DALAM ).
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 NULL
nilai.
2.2 BERGABUNG DENGAN BENAR atau BERGABUNG KANAN
Ini JOIN
mengembalikan 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 NULL
nilai.
2.3 BERGABUNG FULL OUTER atau FULL JOIN
Ini JOIN
menggabungkan LEFT OUTER JOIN
dan RIGHT OUTER JOIN
. Ini mengembalikan baris dari tabel mana pun ketika kondisi terpenuhi dan mengembalikan NULL
nilai ketika tidak ada kecocokan.
Dengan kata lain, OUTER JOIN
didasarkan 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`.
Ini didasarkan pada dua kondisi:
JOIN
dibuat pada semua kolom dengan nama yang sama untuk kesetaraan.Ini tampaknya lebih bersifat teoritis dan sebagai hasilnya (mungkin) sebagian besar DBMS bahkan tidak repot-repot mendukung ini.
Ini adalah produk Cartesian dari dua tabel yang terlibat. Hasil dari CROSS JOIN
tidak akan masuk akal di sebagian besar situasi. Selain itu, kita tidak akan membutuhkan ini sama sekali (atau perlu paling tidak, tepatnya).
Ini bukan bentuk yang berbeda dari JOIN
, melainkan merupakan JOIN
( INNER
, OUTER
, dll) dari meja untuk dirinya sendiri.
Bergantung pada operator yang digunakan untuk JOIN
klausa, mungkin ada dua jenis JOIN
s. Mereka
Untuk JOIN
jenis apa pun ( INNER
,, OUTER
dll), jika kita HANYA menggunakan operator persamaan (=), maka kita mengatakan bahwa itu JOIN
adalah EQUI JOIN
.
Ini sama seperti EQUI JOIN
tetapi memungkinkan semua operator lain seperti>, <,> = dll.
Banyak yang menganggap keduanya
EQUI JOIN
dan ThetaJOIN
mirip denganINNER
,OUTER
dllJOIN
. Tapi saya sangat percaya bahwa ini adalah kesalahan dan membuat ide-ide itu kabur. KarenaINNER JOIN
,OUTER JOIN
dll semua terhubung dengan tabel dan data mereka sedangkanEQUI JOIN
danTHETA JOIN
hanya terhubung dengan operator yang kami gunakan di yang sebelumnya.Sekali lagi, ada banyak orang yang menganggapnya
NATURAL JOIN
sebagai "aneh"EQUI JOIN
. Sebenarnya, itu benar, karena syarat pertama yang saya sebutkanNATURAL JOIN
. Namun, kita tidak harus membatasi itu hanya untukNATURAL JOIN
s saja.INNER JOIN
s,OUTER JOIN
s dll bisa menjadiEQUI JOIN
terlalu.
Definisi:
BERGABUNG adalah cara untuk meminta data yang digabungkan bersama dari beberapa tabel secara bersamaan.
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.
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.
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.
GABUNG-GABUNG: Gabung ini tidak menggabungkan / menggabungkan melainkan melakukan produk Cartesian.
Catatan: Self-JOIN dapat diraih oleh INNER-JOIN, OUTER-JOIN dan CROSS-JOIN berdasarkan persyaratan tetapi tabel harus bergabung dengan dirinya sendiri.
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;
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.
UNION JOIN
. Sekarang dibuat usang dalam SQL: 2003.
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.
Inilah sebabnya mengapa diagram Venn menjelaskannya secara tidak akurat, karena JOIN membuat produk kartesius di antara dua tabel yang digabungkan. Wikipedia menggambarkannya dengan baik:
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
An INNER JOIN
hanya disaring di CROSS JOIN
mana predikat filter disebut Theta
dalam 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 INNER
adalah opsional (kecuali dalam MS Access).
( lihat artikel untuk contoh hasil )
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.
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_UPDATE
kolom dalam database Sakila ).
Inilah sintaksinya:
SELECT *
FROM actor
NATURAL JOIN film_actor
NATURAL JOIN film
Sekarang, OUTER JOIN
sedikit berbeda dari INNER JOIN
karena ia menciptakan UNION
beberapa 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 OUTER
bersifat opsional, di sini.
OUTER JOIN
hadir dalam tiga rasa:
LEFT [ OUTER ] JOIN
: Tabel kiri JOIN
ungkapan ditambahkan ke gabungan seperti yang ditunjukkan di atas.RIGHT [ OUTER ] JOIN
: Tabel kanan JOIN
ungkapan ditambahkan ke serikat seperti yang ditunjukkan di atas.FULL [ OUTER ] JOIN
: Kedua tabel JOIN
ekspresi 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 JOIN
baru - baru ini )
Ada beberapa sintaks historis dan usang di Oracle dan SQL Server, yang OUTER JOIN
sudah 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.
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 JOIN
cocok dengan apa pun di "sisi lain dari GABUNG". Singkat cerita: Ini untuk mengisi data yang jarang dalam laporan. Sangat berguna!
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_id
predikat 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.
Ini adalah kebalikan dari SEMI BERGABUNG ( hati-hati untuk tidak menggunakan NOT IN
meskipun , 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.
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 JOIN
akan menjadi teman Anda. Jika Anda orang SQL Server, maka Anda tahu JOIN
jenis 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 JOIN
atau APPLY
ekspresi benar-benar "subquery berkorelasi" yang menghasilkan beberapa baris. Tetapi jika kita mengizinkan "subqueries berkorelasi", kita juga dapat berbicara tentang ...
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.
MULTISET
menghasilkan 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
, OUTER
dan CROSS JOIN
yang biasanya disebutkan. Lebih detail di artikel saya . Dan tolong, berhenti menggunakan diagram Venn untuk mengilustrasikannya.
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.