เหตุผลที่ต้องชอบ RIGHT JOIN มากกว่า LEFT JOIN


18

ถ้าฉันเข้าใจถูกต้องทุกคนRIGHT JOIN:

SELECT Persons.*, Orders.*
FROM Orders
RIGHT JOIN Persons ON Orders.PersonID = Persons.ID

สามารถแสดงเป็นLEFT JOIN:

SELECT Persons.*, Orders.*
FROM Persons
LEFT JOIN Orders ON Persons.ID = Orders.PersonID

ความคิดเห็นส่วนตัวของฉันคือเจตนาของแถลงการณ์:

  • ก่อนได้รับ Persons
  • จากนั้นขยาย / ทำซ้ำPersonsตามที่จำเป็นเพื่อให้ตรงกับOrders

แสดงได้ดีกว่าโดยคำสั่งของPersons LEFT JOIN Ordersกว่าสั่งย้อนกลับOrders RIGHT JOIN Persons(และฉันไม่เคยใช้RIGHT JOINเป็นผล)

มีสถานการณ์ใดบ้างที่RIGHT JOINเป็นที่ต้องการ? หรือมีกรณีการใช้งานที่RIGHT JOINสามารถทำสิ่งที่LEFT JOINไม่สามารถ?


12
ฉันจำไม่ได้ว่ากรณีหนึ่งที่ฉันต้องการเข้าร่วมถูกต้อง ฉันมีกรณีที่แผนการดำเนินการของแบบสอบถามพลิกการรวมด้านซ้ายเข้าร่วมอย่างถูกต้องด้วยเหตุผลด้านประสิทธิภาพ แต่จากจุดยืนการเขียนโค้ดล้วนๆฉันไม่จำการเขียนที่ถูกต้องได้เลย
Brandon

2
ฉันไม่เห็นสิ่งนี้เป็นคำถามเกี่ยวกับ "การอธิบายการเขียนหรือการดีบักโค้ด" มันถามว่าทำไมภาษามีคุณสมบัติสองอย่างที่เห็นได้ชัดว่าทำสิ่งเดียวกันหากมีความแตกต่างระหว่างพวกเขาจริง ๆ และถ้าไม่ใช่เมื่อต้องการ "ที่ไม่ชัดเจน"
Philip Kendall

1
ไม่การเข้าร่วมด้านซ้ายมักจะรวบรวมสิ่งที่คุณต้องการอย่างรัดกุมที่สุดและง่ายกว่าที่จะให้เหตุผล ที่ทำงานของฉันเรามีมาตรฐานเพื่อป้องกันการเชื่อมต่อที่ถูกต้องเนื่องจากไม่มีกรณีที่จำเป็น (เช่นพวกเขาสามารถถูกแทนที่ด้วยการเข้าร่วมด้านซ้ายตรงข้ามเสมอ)
mgw854

8
ฉันรีเซ็ตคะแนนปิด - คำถามนี้อยู่ในหัวข้อที่นี่เนื่องจากการทำความเข้าใจความแตกต่างระหว่างการรวมมีผลต่อการออกแบบซอฟต์แวร์ (การออกแบบฐานข้อมูลเป็นส่วนหนึ่งของการออกแบบซอฟต์แวร์เช่นเดียวกับอัลกอริทึมที่อาจสืบค้นฐานข้อมูล) มันอาจเป็นหัวข้อที่ผู้ดูแลระบบฐานข้อมูลและอาจมีซ้ำด้วยเช่นกัน
โธมัสโอเวนส์

1
ฉันไม่แน่ใจว่าคุณกำลังแนะนำที่RIGHT JOINแนะนำหรือมากกว่าทั่วไป ถ้านั่นคือหลักฐานของคุณมันไม่ถูกต้อง ฉันไม่สามารถนึกถึงเวลาที่ฉันเคยเห็นการเข้าร่วมที่ถูกต้องที่ใช้ในโค้ดหรือในตัวอย่าง มันหรือJOIN ในบางกรณีคุณอาจเห็นLEFT OUTER JOIN FULL OUTER JOIN
JimmyJames

คำตอบ:


12

ขึ้นอยู่กับข้อกำหนดที่คุณพยายามจะเติมเต็ม

มันไม่เหมือนกันที่จะพูดว่า: "ขอให้ทุกคนและคำสั่งซื้อที่สอดคล้องกัน"ว่า"ฉันต้องการคำสั่งซื้อทั้งหมดกับบุคคลที่เกี่ยวข้อง"โดยเฉพาะอย่างยิ่งถ้าคุณจะใช้is nullเพื่อนำแถวที่ไม่มีการจับคู่ที่ตรงกัน นั่นคือสิ่งที่ฉันเรียกว่า "ตารางที่โดดเด่น" ซึ่งเป็นตารางที่ฉันต้องการดึงแถวจากไม่ว่าจะไม่มีแถวที่มีความเสียหายในด้านอื่น ๆ ของการเข้าร่วม

ดูรูปนี้แล้วคุณจะสังเกตเห็นว่ามันไม่เหมือนกัน:

ป้อนคำอธิบายรูปภาพที่นี่

แหล่งที่มาของภาพเป็นบทความที่ดีเยี่ยมนี้

แต่คุณมีสิทธิ์ในการที่ทั้งสองความต้องการสามารถปฏิบัติตามด้วยการเข้าร่วมเพียงแค่กลับคำสั่งของตารางในการเข้าร่วม

แต่ฉันเดาว่าสำหรับคนตะวันตกที่คุ้นเคยกับการเขียนจากซ้ายไปขวามันเป็นธรรมชาติมากกว่าที่จะใช้การรวมซ้ายเป็นการรวมขวาเนื่องจากเราเห็นราวกับว่าเราต้องการให้การรวมอยู่ในทิศทางเดียวกันหรือในลำดับเดียวกับselectคอลัมน์เอ็ด

ดังนั้นเหตุผลที่เป็นไปได้ที่จะชอบการเข้าร่วมที่เหมาะสมคือเพราะในวัฒนธรรมของคุณคุณเขียนจากขวาไปซ้าย (เช่นในระบบการเขียนภาษาอาหรับหรือภาษาฮิบรู) และคุณมักจะคิดแบบนั้นซึ่งอาจหมายถึงสมองของคุณ .

นักภาษาศาสตร์บางคนคิดว่าภาษาของคุณมีอิทธิพลต่อวิธีคิดของคุณ: https://www.edge.org/conversation/lera_boroditsky-how-does-our-language-shape-the-way-we-think


1
ฉันเริ่มคิดตามบรรทัดเหล่านี้ แต่ฉันไม่คิดว่ามันถูกต้อง ฉันเริ่มจินตนาการการเขียน SQL เป็นภาษาฮีบรู (ซึ่งฉันไม่เคยทำมาก่อน) ตกลง: ชิดขอบขวา, จากขวาไปซ้าย, จากบนลงล่าง คุณจะยังคงพูดถึงตาราง A ก่อนแล้วตาราง B ด้วยการเข้าร่วมที่ถูกต้องคุณจะไม่รวม (โดยเฉพาะในกรณีที่เป็นโมฆะ) ส่วนใหญ่หรือทั้งหมดของตารางที่กล่าวถึงก่อน ผมคิดว่าจิตใจมนุษย์มีแนวโน้มที่จะเชื่อมโยงครั้งแรกกับหลักและที่สำคัญที่สุด สิ่งนี้เกิดขึ้นโดยไม่คำนึงถึงทิศทางการเขียน คุณสามารถเรียกพวกเขาว่า "FIRST JOIN" และ "SECOND JOIN" และความลำเอียงนี้จะยังคงเกิดขึ้น
Mike รองรับโมนิกา

ฉันได้รวมลิงค์ไปยังรูปภาพที่คุณแสดงด้านล่าง
Jon Raynor

@ ไมค์ฉันไม่แนะนำให้คนเขียน SQL เป็นภาษาอารบิกหรือฮิบรู เพียงแค่นั้นการวางแนวของภาษาแม่ของคุณอาจเป็นเหตุผลสำหรับคุณที่จะชอบร่วมขวา แต่นั่นเป็นเพียงความเป็นไปได้ ฉันพบว่าซ้ายเข้าร่วมเป็นธรรมชาติมากขึ้น
Tulains Córdova

ตอนนี้ฉันให้เครดิตแก่ผู้สร้างภาพ ฉันมีมันมาหลายปีใน HD ของฉันและฉันจำไม่ได้ว่ามันมาจาก
ไหน

ฉันพูดภาษาฮิบรูอย่างคล่องแคล่วและฉันยังพบLEFT JOINความเป็นธรรมชาติมากกว่า
Zev Spitz

3

ไม่มีสิ่งใด (ที่ฉันรู้) ที่สามารถทำได้ด้วยการเข้าร่วมที่ถูกต้องที่ไม่สามารถทำได้ด้วยการเข้าร่วมทางซ้าย แต่บางครั้งไวยากรณ์ที่มีการรวมซ้ายนั้นน่าเกลียด สมมติว่าคุณมีตารางต่อไปนี้:

Persons
ID | Name

Orders
ID | CustomerId | other unimportant stuff

SpecialOrderDetails
ID | OrderId | other stuff

สมมติว่าคุณต้องการรับรายชื่อของคนทั้งหมดในฐานข้อมูลของคุณและคำสั่งซื้อใด ๆ ที่พวกเขามีรายละเอียดการสั่งซื้อพิเศษ (เราจะบอกว่าคำสั่งซื้อทั้งหมดไม่ได้มีรายละเอียดคำสั่งพิเศษ) โดยปกติแล้วคุณจะเข้าร่วมการสั่งซื้อด้านซ้ายจากคน แต่คุณต้องเข้าร่วมในรายละเอียดการสั่งซื้อพิเศษ หากคุณใช้การรวมภายในที่นั่นจะทำให้การเข้าร่วมด้านซ้ายจากบุคคลเพื่อการสั่งซื้อเป็นการรวมภายในอย่างมีประสิทธิภาพ IE: นี่คือสิ่งที่คุณต้องการจะทำ แต่ไม่ได้ผล (มันจะไม่รวมใครก็ตามที่ไม่มีคำสั่งพิเศษ):

select p.*, o.*, d.*
from Persons p
left join Orders o on o.CustomerId = p.Id
inner join SpecialOrderDetails d on d.OrderId = o.Id

ดังนั้นคุณสามารถเขียนซ้ำได้ดังนี้:

--get all the people without a special order
select p.*, NULL, NULL, ... --NULLs placeholders for all the fields from OrderDetails and SpecialOrderDetails
from Persons p
left join Orders o on o.CustomerId = p.Id
left join SpecialOrderDetails d on d.OrderId = o.Id
where o.Id is null 

union

--get all the people with a special order
select p.*, o.*, d.*
from Persons p
inner join Orders o on o.CustomerId = p.Id
inner join SpecialOrderDetails d on d.OrderId = o.Id

ไม่ชัดเจนอย่างแน่นอน (สมมติว่าไม่มีความคิดเห็น) แต่ทำงานได้ หากนี่คือสิ่งที่มากกว่าหนึ่งครั้ง (เช่นบางสิ่งบางอย่างที่ใครบางคนกำลังจะต้องกลับมาและรักษาบางวัน) การใช้การเข้าร่วมที่ถูกต้องอาจทำให้ชัดเจนว่าเจตนาคืออะไร

select p.*, o.*, d.*
from Orders o
inner join SpecialOrderDetails d on d.OrderId = o.Id
right join Persons p on p.Id = o.CustomerId

ซึ่งค่อนข้างสั้นและชัดเจนมากขึ้น (แต่ถ้าใครก็ตามที่อ่านมันจะเข้าใจถูกต้อง) โปรดทราบว่าสิ่งนี้สามารถเขียนด้วยการรวมซ้าย แต่ต้องมีการเข้าร่วมที่ซ้อนกัน (ซึ่งบางคนอาจคุ้นเคยกับการรวมขวามากกว่า)

select p.*, o.*, d.*
from Persons p
left join Orders o 
    inner join SpecialOrderDetails d on d.OrderId = o.Id
on o.CustomerId = p.Id

ณ จุดนี้มันเป็นตัวเลือกของสิ่งที่ชัดเจนที่สุดและสิ่งที่คนส่วนใหญ่จะเข้าใจ (คุณจะรู้วิธีการ Google ไวยากรณ์นั้นถ้าคุณไม่ทราบว่ามันถูกเรียกว่าการเข้าร่วมซ้อนกัน?)

กล่าวโดยสรุปคุณไม่ต้องการการรวมที่ถูกต้องแต่อาจทำให้อ่านง่ายขึ้น


ฉันคิดว่าบางทีคุณแค่ถนัดขวา
Robert Harvey

SELECT p.*, o.*, d.* FROM Persons p LEFT JOIN Orders o ON o.CustomerID = p.ID LEFT JOIN SpecialOrders d ON o.Id = d.OrderIDฉันไม่ได้ทำตามเหตุผลที่คุณไม่สามารถเขียนหลายซ้ายร่วมในกรณีนี้:
Zev Spitz

@ RobertHarvey ฉันเป็นคน แต่ฉันไม่แน่ใจว่าสิ่งที่ต้องใช้จะทำอย่างไรกับมัน
Becuzz

@ZevSpitz บางทีมันอาจจะไม่ชัดเจนจากสิ่งที่ฉันเขียน แต่ความคิดคือคุณต้องการเพียงเขตข้อมูลจากการสั่งซื้อเฉพาะในกรณีที่มีบันทึกรายละเอียดคำสั่งซื้อพิเศษเช่น เหลือให้เข้าร่วมพวกเขาก็ต่อเมื่อมีคู่ของพวกเขาอยู่
Becuzz

-1

ฉันเห็น RIGHT JOIN ถูกใช้เพื่อวัตถุประสงค์ในการจำลองแบบ / ผสาน สมมติว่าฉันมีสองตาราง A และ B A อยู่ทางซ้ายและ B อยู่ทางขวา สมมติว่าฉันต้องการทำซ้ำข้อมูลระหว่างสองตารางนี้เพื่อให้เท่าเทียมกัน

ถ้าฉันต้องการแสดงข้อมูลทั้งหมดที่อยู่ใน A แต่ไม่ใช่ใน B มันจะเป็นการเข้าร่วมทางซ้าย ถ้าฉันต้องการแสดงข้อมูลทั้งหมดใน B ที่ไม่ได้อยู่ใน A มันจะเข้าร่วมทันที

ดังนั้นบางครั้งซ้ายและขวามีประโยชน์เมื่อทำการผสานและจำลองข้อมูลเพื่อเก็บสิ่งต่าง ๆ ในอนาคต

นอกเหนือจากนั้นฉันไม่เห็นเหตุผลอื่นใดที่จะใช้การเข้าร่วม RIGHT เนื่องจากการรวม RIGHT ทั้งหมดสามารถแปลงเป็น LEFT JOIN หรือในทางกลับกัน LEFT JOIN ทั้งหมดจะถูกแปลงเป็น RIGHT JOIN ขึ้นอยู่กับวิธีการสั่งหรือมองเห็นตาราง ดังนั้นมันจะเป็นเรื่องของการตั้งค่าในกรณีอื่น ๆ

นี่คือลิงค์ที่ดีในการมองเห็น SQL Joins

http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins


-1

การเข้าร่วมซ้ายไม่ตรงข้ามกับการเข้าร่วมที่ถูกต้องตรวจสอบกรณีต่อไปนี้ซึ่งให้ผลลัพธ์ที่แตกต่าง

select * from 
(select 1 as x  where 1=1) a left join 
(select 1 as x  where 1=0) b on a.x=b.x inner join 
(select 1 as x  where 1=1) c on b.x=c.x

select * from 
(select 1 as x where 1=1) c inner join 
(select 1 as x where 1=0) b on c.x=b.x right join 
(select 1 as x where 1=1) a on b.x=a.x

ตาราง b anc c เป็น allways ด้านในที่เข้าร่วม แต่ใน a แรกจะถูกรวมเข้ากับคนอื่น ๆ และใน a ที่สองเข้าร่วม

การเข้าร่วมด้านซ้ายจะไม่ส่งคืนแถวใด ๆ ในขณะที่การเข้าร่วมที่ถูกต้องจะส่งคืนแถว


สิ่งนี้อ่านเพิ่มเติมเช่นความเห็นแทนเจนต์ดูวิธีการตอบ
gnat

-2

ไม่มีเหตุผลใดที่จะชอบRIGHT JOINและLEFT JOINชัดเจนกว่า:

เลือกบุคคล *, คำสั่งซื้อ * จากบุคคลด้านซ้ายเข้าร่วมคำสั่งซื้อกับ Persons.ID = Orders.PersonID

เนื่องจากช่วยให้คุณเห็นตารางที่ถูกสอบถามได้ทันที ในขณะที่RIGHT JOIN:

เลือกบุคคล *, คำสั่งซื้อ * จากคำสั่งซื้อที่ถูกต้องเข้าร่วมบุคคลใน Orders.PersonID = บุคคล

JOINตารางแรกที่เขียนหลังจากที่

RIGHT JOINจากประสบการณ์ของผมผมไม่เคยเห็น


1
สิ่งนี้เพิ่มคำถามอะไร คำถามไม่ใช่ความแตกต่างอะไร ; คำถามคือทำไมฉันจึงควรใช้RIGHT JOIN? .
Zev Spitz

@ZevSpitz คุณถามถึงเหตุผลที่จะเลือกอันไหนฉันให้เหตุผลกับคุณ เคสที่ใช้ไม่สำคัญเพราะเป็นเรื่องของรสนิยม
kirie
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.