SQL คืออะไรJOINและมีประเภทแตกต่างกันอย่างไร
SQL คืออะไรJOINและมีประเภทแตกต่างกันอย่างไร
คำตอบ:
SQL JOINอะไรSQL JOIN เป็นวิธีการดึงข้อมูลจากสองตารางฐานข้อมูลหรือมากกว่านั้น
SQL JOIN?มีทั้งหมดห้าJOINs พวกเขาเป็น :
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ข้อสามารถมีได้ทั้งสองประเภทของJOINs พวกเขาเป็น
สำหรับสิ่งที่JOINประเภท ( INNER, OUTERฯลฯ ) ถ้าเราใช้เฉพาะผู้ประกอบการความเท่าเทียมกัน (=) แล้วเราบอกว่าเป็นJOINEQUI JOIN
สิ่งนี้เหมือนกับEQUI JOINแต่อนุญาตให้ตัวดำเนินการอื่นทั้งหมดเช่น>, <,> = เป็นต้น
หลายคนคิดว่าทั้งสอง
EQUI JOINและทีJOINคล้ายกับINNER,OUTERฯลฯJOINs แต่ฉันเชื่ออย่างยิ่งว่ามันเป็นความผิดพลาดและทำให้ความคิดที่คลุมเครือ เพราะINNER JOIN,OUTER JOINฯลฯ มีการเชื่อมต่อทั้งหมดที่มีตารางและข้อมูลของพวกเขาในขณะที่EQUI JOINและTHETA JOINมีการเชื่อมต่อเฉพาะกับผู้ประกอบการที่เราใช้ในอดีตอีกครั้งมีหลายคนที่พิจารณา
NATURAL JOINเป็นEQUI JOIN"แปลกประหลาด"NATURAL JOINในความเป็นจริงมันเป็นความจริงเพราะของสภาพแรกที่ผมกล่าวถึง อย่างไรก็ตามเราไม่จำเป็นต้อง จำกัด เพียงNATURAL JOINอย่างเดียวINNER JOINs,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)
ฉันพบว่ามันใช้งานได้ดีอ่านได้และไม่ได้ใช้บ่อยเพียงพอ