SQL คืออะไรJOIN
และมีประเภทแตกต่างกันอย่างไร
SQL คืออะไรJOIN
และมีประเภทแตกต่างกันอย่างไร
คำตอบ:
SQL JOIN
อะไรSQL JOIN
เป็นวิธีการดึงข้อมูลจากสองตารางฐานข้อมูลหรือมากกว่านั้น
SQL JOIN
?มีทั้งหมดห้าJOIN
s พวกเขาเป็น :
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
ในประเภทนี้JOIN
เราจะได้รับรายงานทั้งหมดที่ตรงกับเงื่อนไขในทั้งสองตารางและไม่มีการรายงานระเบียนในทั้งสองตารางที่ไม่ตรงกัน
กล่าวอีกนัยหนึ่งINNER JOIN
จะขึ้นอยู่กับข้อเท็จจริงเดียวที่: เฉพาะรายการที่ตรงกันในทั้งสองตารางควรแสดงรายการ
ทราบว่าJOIN
โดยไม่ต้องอื่น ๆJOIN
คำหลัก (เช่นINNER
, OUTER
, LEFT
ฯลฯ ) INNER JOIN
เป็น กล่าวอีกนัยหนึ่งJOIN
คือน้ำตาลซินแทคติกสำหรับINNER JOIN
(ดู: ความแตกต่างระหว่างเข้าร่วมและเข้าร่วมภายใน )
OUTER JOIN
ดึง
ไม่ว่าจะเป็นแถวที่ตรงกันจากตารางหนึ่งและแถวทั้งหมดในตารางอื่นหรือแถวทั้งหมดในตารางทั้งหมด (ไม่สำคัญว่าจะมีการจับคู่หรือไม่ก็ตาม)
การเข้าร่วม Outer มีสามชนิด:
2.1 ซ้ายซ้ายเข้าร่วมหรือซ้ายเข้าร่วม
การเข้าร่วมนี้จะส่งคืนแถวทั้งหมดจากตารางด้านซ้ายพร้อมกับแถวที่ตรงกันจากตารางด้านขวา หากไม่มีคอลัมน์ที่ตรงกับในตารางด้านขวามันจะส่งคืนNULL
ค่า
2.2 เข้าร่วมด้านขวาหรือเข้าร่วมขวา
สิ่งนี้JOIN
จะคืนค่าแถวทั้งหมดจากตารางด้านขวาพร้อมกับแถวที่ตรงกันจากตารางด้านซ้าย หากไม่มีคอลัมน์ที่ตรงกับในตารางด้านซ้ายมันจะคืนNULL
ค่า
2.3 เต็มเต็มเข้าร่วมหรือเต็มเข้าร่วม
นี้JOIN
รวมและLEFT OUTER JOIN
RIGHT OUTER JOIN
มันจะส่งคืนแถวจากทั้งสองตารางเมื่อตรงตามเงื่อนไขและคืนNULL
ค่าเมื่อไม่มีการจับคู่
กล่าวอีกนัยหนึ่งOUTER JOIN
ขึ้นอยู่กับความจริงที่ว่า: เฉพาะรายการที่ตรงกันในหนึ่งในตาราง (ขวาหรือซ้าย) หรือทั้งสองของตาราง (เต็ม) ควรแสดงรายการ
Note that `OUTER JOIN` is a loosened form of `INNER JOIN`.
มันขึ้นอยู่กับเงื่อนไขสองประการ:
JOIN
จะทำบนคอลัมน์ทั้งหมดที่มีชื่อเดียวกันเพื่อความเท่าเทียมกันสิ่งนี้ดูเหมือนจะเป็นทฤษฎีมากกว่าปกติและเป็นผล (อาจ) DBMS ส่วนใหญ่ไม่สนใจที่จะสนับสนุนสิ่งนี้
มันเป็นผลิตภัณฑ์คาร์ทีเซียนของทั้งสองตารางที่เกี่ยวข้อง ผลลัพธ์ของ a CROSS JOIN
จะไม่สมเหตุสมผลในสถานการณ์ส่วนใหญ่ ยิ่งกว่านั้นเราไม่ต้องการสิ่งนี้เลย (หรือต้องการอย่างน้อยก็แม่นยำ)
มันไม่ได้เป็นรูปแบบที่แตกต่างกันJOIN
ค่อนข้างจะเป็นJOIN
( INNER
, OUTER
ฯลฯ ) ของตารางกับตัวเอง
ทั้งนี้ขึ้นอยู่กับผู้ประกอบการที่ใช้สำหรับJOIN
ข้อสามารถมีได้ทั้งสองประเภทของJOIN
s พวกเขาเป็น
สำหรับสิ่งที่JOIN
ประเภท ( INNER
, OUTER
ฯลฯ ) ถ้าเราใช้เฉพาะผู้ประกอบการความเท่าเทียมกัน (=) แล้วเราบอกว่าเป็นJOIN
EQUI JOIN
สิ่งนี้เหมือนกับEQUI JOIN
แต่อนุญาตให้ตัวดำเนินการอื่นทั้งหมดเช่น>, <,> = เป็นต้น
หลายคนคิดว่าทั้งสอง
EQUI JOIN
และทีJOIN
คล้ายกับINNER
,OUTER
ฯลฯJOIN
s แต่ฉันเชื่ออย่างยิ่งว่ามันเป็นความผิดพลาดและทำให้ความคิดที่คลุมเครือ เพราะINNER JOIN
,OUTER JOIN
ฯลฯ มีการเชื่อมต่อทั้งหมดที่มีตารางและข้อมูลของพวกเขาในขณะที่EQUI JOIN
และTHETA JOIN
มีการเชื่อมต่อเฉพาะกับผู้ประกอบการที่เราใช้ในอดีตอีกครั้งมีหลายคนที่พิจารณา
NATURAL JOIN
เป็นEQUI JOIN
"แปลกประหลาด"NATURAL JOIN
ในความเป็นจริงมันเป็นความจริงเพราะของสภาพแรกที่ผมกล่าวถึง อย่างไรก็ตามเราไม่จำเป็นต้อง จำกัด เพียงNATURAL JOIN
อย่างเดียวINNER JOIN
s,OUTER JOIN
ฯลฯ อาจเป็นEQUI JOIN
เช่นกัน
ความหมาย:
เข้าร่วมเป็นวิธีการค้นหาข้อมูลที่รวมเข้าด้วยกันจากหลายตารางพร้อมกัน
เกี่ยวกับ RDBMS มีการรวม 5 ประเภท:
เข้าร่วม Equi:รวมระเบียนทั่วไปจากสองตารางตามเงื่อนไขความเท่าเทียมกัน ในทางเทคนิคการเข้าร่วมทำได้โดยใช้ตัวดำเนินการเท่าเทียมกัน (=) เพื่อเปรียบเทียบค่าของคีย์หลักของตารางหนึ่งและค่าคีย์ต่างประเทศของตารางอื่นดังนั้นชุดผลลัพธ์จึงรวมเร็กคอร์ด (จับคู่) ทั่วไปจากทั้งสองตาราง สำหรับการติดตั้งโปรดดูที่ INNER-JOIN
Natural-Join: เป็นรุ่นที่ได้รับการปรับปรุงของ Equi-Join ซึ่งการดำเนินการ SELECT จะไม่แสดงคอลัมน์ที่ซ้ำกัน สำหรับการติดตั้งโปรดดูที่ INNER-JOIN
Non-Equi-Join:เป็นการย้อนกลับของการเข้าร่วม Equi โดยที่เงื่อนไขการเข้าร่วมถูกใช้นอกเหนือจากตัวดำเนินการเท่ากัน (=) เช่น,! =, <=,> =,>, <หรือระหว่าง ฯลฯ สำหรับการนำไปใช้ให้ดู INNER-JOIN
เข้าร่วมตัวเอง::พฤติกรรมที่กำหนดเองของการเข้าร่วมที่ตารางรวมกับตัวเอง; โดยทั่วไปสิ่งนี้จำเป็นสำหรับการสอบถามตารางการอ้างอิงตนเอง (หรือเอนทิตีความสัมพันธ์ของ Unary) สำหรับการนำไปใช้ให้ดูที่ INNER-JOIN
ผลิตภัณฑ์คาร์ทีเซียน:มันรวมบันทึกทั้งหมดของตารางทั้งสองโดยไม่มีเงื่อนไขใด ๆ ในทางเทคนิคแล้วมันจะส่งคืนชุดผลลัพธ์ของแบบสอบถามโดยไม่มี WHERE-Clause
ตามความกังวลและความก้าวหน้าของ SQL มีการรวม 3 แบบและการรวม RDBMS ทั้งหมดสามารถทำได้โดยใช้การรวมประเภทนี้
ภายในเข้าร่วม:มันผสาน (หรือรวม) จับคู่แถวจากสองตาราง การจับคู่จะกระทำตามคอลัมน์ทั่วไปของตารางและการดำเนินการเปรียบเทียบ หากเงื่อนไขตามความเท่าเทียมกัน: EQUI-JOIN ดำเนินการมิฉะนั้นไม่ใช่เข้าร่วม EQUI
OUTER-JOIN:เป็นการผสาน (หรือรวม) การจับคู่แถวจากสองตารางและแถวที่ไม่ตรงกันด้วยค่า NULL อย่างไรก็ตามสามารถปรับแต่งการเลือกแถวที่ไม่ตรงกันเช่นการเลือกแถวที่ไม่ตรงกันจากตารางแรกหรือตารางที่สองตามประเภทย่อย: LEFT OUTER JOIN และ RIGHT OUTER JOIN
2.1 LEFT Outer JOIN (aka, LEFT-JOIN): ส่งคืนแถวที่ตรงกันจากสองตารางและไม่ตรงกันจากตาราง LEFT (เช่นตารางแรก) เท่านั้น
2.2 RIGHT Outer JOIN (aka, RIGHT-JOIN): ส่งคืนแถวที่ตรงกันจากสองตารางและไม่ตรงกันจากตาราง RIGHT เท่านั้น
2.3 FULL OUTER JOIN (aka OUTER JOIN): ส่งคืนการจับคู่และไม่ตรงกันจากทั้งสองตาราง
CROSS-JOIN: การเข้าร่วมนี้ไม่ได้รวม / รวมเข้าด้วยกัน แต่จะทำงานร่วมกับผลิตภัณฑ์คาร์ทีเซียน
หมายเหตุ: การเข้าร่วมด้วยตนเองสามารถทำได้โดยใช้ INNER-JOIN, OUTER-JOIN และ CROSS-JOIN ตามความต้องการ แต่ตารางจะต้องเข้าร่วมกับตัวเอง
1.1: INNER-JOIN: การติดตั้ง Equi-join
SELECT *
FROM Table1 A
INNER JOIN Table2 B ON A.<Primary-Key> =B.<Foreign-Key>;
1.2: ภายใน -JININ: การดำเนินการตามธรรมชาติเข้าร่วม
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: ภายในเข้าร่วมกับการใช้งานแบบไม่เข้าร่วม Equi
Select *
FROM Table1 A INNER JOIN Table2 B On A.Pk <= B.Fk;
1.4: ภายในเข้าร่วมด้วยตนเองเข้าร่วม
Select *
FROM Table1 A1 INNER JOIN Table1 A2 On A1.Pk = A2.Fk;
2.1: นอกเข้าร่วม (เต็มภายนอกเข้าร่วม)
Select *
FROM Table1 A FULL OUTER JOIN Table2 B On A.Pk = B.Fk;
2.2: ซ้ายเข้าร่วม
Select *
FROM Table1 A LEFT OUTER JOIN Table2 B On A.Pk = B.Fk;
2.3: เข้าร่วมทางขวา
Select *
FROM Table1 A RIGHT OUTER JOIN Table2 B On A.Pk = B.Fk;
3.1: CROSS JOIN
Select *
FROM TableA CROSS JOIN TableB;
3.2: CROSS เข้าร่วมด้วยตนเองเข้าร่วม
Select *
FROM Table1 A1 CROSS JOIN Table1 A2;
//หรือ//
Select *
FROM Table1 A1,Table1 A2;
intersect
/ except
/ union
; ที่นี่วงกลมคือแถวที่ส่งกลับโดยleft
& right
join
ตามที่ป้ายกำกับหมายเลขระบุว่า ภาพ AXB ไร้สาระ cross join
= inner join on 1=1
& เป็นกรณีพิเศษของแผนภาพแรก
UNION JOIN
กำหนด ตอนนี้ล้าสมัยแล้วใน SQL: 2003
คำตอบอื่น ๆ ที่น่าสนใจที่สุดประสบกับปัญหาทั้งสองนี้:
เมื่อเร็ว ๆ นี้ฉันได้เขียนบทความเกี่ยวกับหัวข้อ: คู่มือที่ครอบคลุมไม่สมบูรณ์สำหรับวิธีการเข้าร่วมตารางใน SQL ที่หลากหลายซึ่งอาจสรุปได้ที่นี่
นี่คือเหตุผลที่ไดอะแกรมของเวนน์อธิบายไม่ถูกต้องเนื่องจากการเข้าร่วมสร้างผลิตภัณฑ์คาร์ทีเซียนระหว่างสองตารางที่เข้าร่วม Wikipedia แสดงให้เห็นเป็นอย่างดี:
ไวยากรณ์ SQL CROSS JOIN
สำหรับผลิตภัณฑ์คาร์ทีเซียนคือ ตัวอย่างเช่น:
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
ซึ่งรวมแถวทั้งหมดจากตารางหนึ่งกับแถวทั้งหมดจากตารางอื่น:
ที่มา:
+--------+ +------------+
| day | | department |
+--------+ +------------+
| Jan 01 | | Dept 1 |
| Jan 02 | | Dept 2 |
| ... | | Dept 3 |
| Jan 30 | +------------+
| Jan 31 |
+--------+
ผลลัพธ์:
+--------+------------+
| 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 |
+--------+------------+
หากเราเพิ่งเขียนรายการตารางคั่นด้วยเครื่องหมายจุลภาคเราจะได้รับเหมือนกัน:
-- CROSS JOINing two tables:
SELECT * FROM table1, table2
An INNER JOIN
เป็นเพียงตัวกรองCROSS JOIN
ที่เรียกว่าตัวกรองคำTheta
ในพีชคณิตเชิงสัมพันธ์
ตัวอย่างเช่น
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
โปรดทราบว่าคำหลักINNER
นั้นเป็นตัวเลือก (ยกเว้นใน MS Access)
( ดูบทความสำหรับตัวอย่างผลลัพธ์ )
Theta-JOIN ชนิดพิเศษคือ equi JOIN ซึ่งเราใช้มากที่สุด เพรดิเคตจะรวมคีย์หลักของตารางหนึ่งโดยมี foreign key ของอีกตารางหนึ่ง ถ้าเราใช้ฐานข้อมูล Sakilaเป็นภาพประกอบเราสามารถเขียน:
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
รวมนักแสดงทั้งหมดเข้ากับภาพยนตร์ของพวกเขา
หรือในบางฐานข้อมูล:
SELECT *
FROM actor
JOIN film_actor USING (actor_id)
JOIN film USING (film_id)
USING()
ไวยากรณ์ช่วยให้การระบุคอลัมน์ที่ต้องมีอยู่บนด้านข้างของทั้ง JOIN ตารางการดำเนินงานและสร้างความเท่าเทียมกันในกริยาทั้งสองคอลัมน์
คำตอบอื่น ๆ มีการระบุไว้ "ประเภท JOIN" นี้แยกจากกัน แต่นั่นก็ไม่สมเหตุสมผล มันเป็นเพียงรูปแบบซินแทกซ์สำหรับ equi JOIN ซึ่งเป็นกรณีพิเศษของ Theta-JOIN หรือ INNER JOIN NAT JOIN JOIN รวบรวมคอลัมน์ทั้งหมดที่ใช้ร่วมกับตารางทั้งสองเข้าร่วมและรวมUSING()
คอลัมน์เหล่านั้นเข้าด้วยกัน ซึ่งไม่ค่อยมีประโยชน์เนื่องจากการจับคู่โดยไม่ตั้งใจ (เช่นLAST_UPDATE
คอลัมน์ในฐานข้อมูล Sakila )
นี่คือไวยากรณ์:
SELECT *
FROM actor
NATURAL JOIN film_actor
NATURAL JOIN film
ตอนนี้OUTER JOIN
มันแตกต่างจากINNER JOIN
ที่มันสร้างUNION
ผลิตภัณฑ์คาร์ทีเซียนหลายอย่าง เราสามารถเขียน:
-- 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>
)
ไม่มีใครต้องการที่จะเขียนหลังดังนั้นเราเขียนOUTER JOIN
(ซึ่งมักจะดีที่สุดโดยฐานข้อมูล)
เช่นเดียวINNER
กับคำหลักOUTER
เป็นตัวเลือกที่นี่
OUTER JOIN
มาในสามรสชาติ:
LEFT [ OUTER ] JOIN
: ตารางด้านซ้ายของJOIN
นิพจน์ถูกเพิ่มเข้ากับสหภาพดังที่แสดงไว้ด้านบนRIGHT [ OUTER ] JOIN
: ตารางด้านขวาของJOIN
นิพจน์ถูกเพิ่มเข้าไปในสหภาพดังที่แสดงไว้ด้านบนFULL [ OUTER ] JOIN
: ทั้งสองตารางของJOIN
นิพจน์จะถูกเพิ่มเข้าไปในยูเนี่ยนสิ่งเหล่านี้สามารถนำมารวมกับคำหลักUSING()
หรือกับNATURAL
( ฉันมีกรณีการใช้งานจริงสำหรับNATURAL FULL JOIN
เมื่อเร็ว ๆ นี้ )
มีบางประวัติศาสตร์ที่ไม่สนับสนุนไวยากรณ์ใน Oracle และ SQL Server ซึ่งได้รับการสนับสนุนOUTER JOIN
แล้วก่อนที่มาตรฐาน SQL มีไวยากรณ์สำหรับสิ่งนี้:
-- 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
ต้องบอกว่าอย่าใช้ไวยากรณ์นี้ ฉันเพิ่งแสดงรายการที่นี่เพื่อให้คุณสามารถจดจำได้จากการโพสต์บล็อกเก่า / รหัสเดิม
OUTER JOIN
มีคนเพียงไม่กี่คนที่รู้สิ่งนี้ แต่มาตรฐาน SQL ระบุการแบ่งพาร์ติชันOUTER JOIN
(และ Oracle ดำเนินการ) คุณสามารถเขียนสิ่งนี้:
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
ส่วนของผลลัพธ์:
+--------+------------+------------+
| 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
ประเด็นคือที่นี่แถวทั้งหมดจากด้านพาร์ติชันของการเข้าร่วมจะสิ้นสุดในผลลัพธ์โดยไม่คำนึงว่าJOIN
อะไรที่ตรงกันใน "ด้านอื่น ๆ ของการเข้าร่วม" สั้นเรื่องสั้น: นี่คือการเติมข้อมูลเบาบางในรายงาน มีประโยชน์มาก!
อย่างจริงจัง? ไม่มีคำตอบอื่น ๆ ที่ได้รับนี้? ไม่แน่นอนเนื่องจากไม่มีไวยากรณ์ดั้งเดิมใน SQL แต่น่าเสียดายที่ (เหมือน ANTI JOIN ด้านล่าง) แต่เราสามารถใช้IN()
และEXISTS()
เช่นเพื่อค้นหานักแสดงทุกคนที่เล่นในภาพยนตร์:
SELECT *
FROM actor a
WHERE EXISTS (
SELECT * FROM film_actor fa
WHERE a.actor_id = fa.actor_id
)
เพรดิเคตWHERE a.actor_id = fa.actor_id
ทำหน้าที่เป็นเพรดิเคตเข้าร่วมกึ่ง หากคุณไม่เชื่อให้ลองใช้แผนการดำเนินการเช่นใน Oracle คุณจะเห็นว่าฐานข้อมูลรันการดำเนินการ SEMI JOIN ไม่ใช่EXISTS()
คำกริยา
นี่เป็นเพียงตรงข้ามของกึ่ง JOIN ( ต้องระวังไม่ให้ใช้NOT IN
แต่เป็นมันมีข้อแม้สำคัญ)
นี่คือนักแสดงทุกคนที่ไม่มีภาพยนตร์:
SELECT *
FROM actor a
WHERE NOT EXISTS (
SELECT * FROM film_actor fa
WHERE a.actor_id = fa.actor_id
)
บางคน (โดยเฉพาะคน MySQL) ก็เขียน ANTI JOIN เช่นนี้:
SELECT *
FROM actor a
LEFT JOIN film_actor fa
USING (actor_id)
WHERE film_id IS NULL
ฉันคิดว่าเหตุผลทางประวัติศาสตร์คือการแสดง
OMG อันนี้เจ๋งเกินไป ฉันเป็นคนเดียวที่พูดถึงมัน? นี่คือแบบสอบถามที่ยอดเยี่ยม:
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
จะพบกับภาพยนตร์ที่สร้างรายได้สูงสุด 5 อันดับแรกต่อนักแสดง ทุกครั้งที่คุณต้องการแบบสอบถาม TOP-N-per-something LATERAL JOIN
จะเป็นเพื่อนของคุณ หากคุณเป็นบุคคล SQL Server คุณจะรู้JOIN
ประเภทนี้ภายใต้ชื่อAPPLY
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
ตกลงบางทีการโกงเพราะLATERAL JOIN
หรือAPPLY
การแสดงออกเป็นจริง "แบบสอบถามย่อยสัมพันธ์" ที่ผลิตหลายแถว แต่ถ้าเราอนุญาตให้ "เคียวรีย่อยที่สัมพันธ์กัน" เราสามารถพูดคุยเกี่ยวกับ ...
สิ่งนี้นำมาใช้จริงโดย Oracle และ Informix (ตามความรู้ของฉัน) แต่สามารถจำลองใน PostgreSQL โดยใช้อาร์เรย์และ / หรือ XML และใน SQL Server โดยใช้ XML
MULTISET
สร้างแบบสอบถามย่อยที่มีความสัมพันธ์และสร้างชุดผลลัพธ์ของแถวในแบบสอบถามภายนอก แบบสอบถามด้านล่างเลือกนักแสดงทุกคนและสำหรับนักแสดงแต่ละคนรวบรวมภาพยนตร์ของพวกเขาในคอลเลกชันซ้อนกัน:
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
ในขณะที่คุณได้เห็นมีหลายประเภทมากขึ้นของการเข้าร่วมมากกว่าเพียงแค่ "น่าเบื่อ" INNER
, OUTER
และCROSS JOIN
ที่มักจะกล่าวถึง รายละเอียดเพิ่มเติมในบทความของฉัน และโปรดหยุดใช้ไดอะแกรมของเวนน์เพื่ออธิบาย
ฉันจะผลักดันสัตว์เลี้ยงฉุนเฉียวของฉัน: คำหลักที่ใช้
หากทั้งสองตารางในทั้งสองด้านของ JOIN มีชื่อต่างประเทศที่ถูกต้อง (เช่นชื่อเดียวกันไม่ใช่แค่ "id) คุณสามารถใช้สิ่งนี้ได้:
SELECT ...
FROM customers JOIN orders USING (customer_id)
ฉันพบว่ามันใช้งานได้ดีอ่านได้และไม่ได้ใช้บ่อยเพียงพอ