เข้าร่วมซ้ายซ้ายจะส่งกลับระเบียนมากกว่าที่มีอยู่ในตารางด้านซ้ายได้อย่างไร


165

ฉันมีการเข้าร่วมด้านซ้ายด้านนอกขั้นพื้นฐานมากเพื่อส่งคืนผลลัพธ์ทั้งหมดจากตารางด้านซ้ายและข้อมูลเพิ่มเติมจากตารางที่ใหญ่กว่ามาก ตารางด้านซ้ายมีระเบียน 4935 แต่เมื่อฉันออกไปด้านนอกเข้าร่วมกับตารางเพิ่มเติมการนับระเบียนนั้นใหญ่กว่ามาก

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

แบบสอบถาม SQL ดังนี้:

SELECT     SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID
FROM         SUSP.Susp_Visits LEFT OUTER JOIN
                      DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum

บางทีฉันได้ทำผิดพลาดในไวยากรณ์หรือความเข้าใจของฉันออกจากซ้ายเข้าร่วมไม่สมบูรณ์หวังว่าบางคนสามารถอธิบายว่าสิ่งนี้อาจเกิดขึ้นได้อย่างไร

ป.ล.

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

แบบสอบถามนี้เป็นการสร้างรายงานอย่างหมดจดและการจับคู่ที่ซ้ำกันก็ทำให้เกิดความสับสน

/ Postscript


5
หากต้องการ "รับบันทึกจำนวนมากที่ส่งคืนตามที่มีอยู่ในตารางด้านซ้าย" คุณจะต้องระบุแถวจากทางด้านขวาเพื่อเลือกว่ามีการแข่งขันหลายรายการหรือไม่
AK

1
คุณจะระบุสิ่งนี้ได้อย่างไร ฉันต้องการนัดแรกที่จะกลับมา
Simon Cross

1
คุณต้องกำหนดความหมายของการแข่งขันนัดแรก คุณต้องการบันทึกที่เร็วที่สุดอัลบั้มที่มีรหัสสูงสุดหรืออะไร
HLGEM

1
หากคุณจับคู่กับคีย์หลักในตารางเพิ่มเติมใบแจ้งยอดของคุณจะถูกต้อง
Godage Prageeth

ฉันมักจะใช้ทรัพยากรเช่นนี้เป็นแผ่นงานโกงเมื่อสร้างแบบสอบถาม หากลิงก์นั้นตายไปเพียงแค่ google sql เข้าร่วม ; พวกเขาเป็นไดอะแกรมของ Venn ประเภทการเข้าร่วมที่ต่างกัน
Zimano

คำตอบ:


190

การเข้าร่วมด้านซ้ายด้านซ้ายจะส่งคืนระเบียนทั้งหมดจากตารางซ้ายเข้าร่วมกับตาราง RIGHT หากเป็นไปได้

หากมีการแข่งขัน แต่ก็จะยังคงกลับแถวทั้งหมดที่ตรงกับดังนั้นหนึ่งแถวซ้ายที่ตรงกับสองแถวที่เหมาะสมจะกลับมาเป็นสองแถวเหมือน INNER JOIN

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


1
เหตุผลในการเข้าร่วมตารางที่ถูกต้องคือฉันจึงได้รับการบันทึกจากด้านซ้ายซึ่งมีอย่างน้อยหนึ่งบันทึกในตารางที่ถูกต้อง แต่ขอบคุณมากสำหรับคำอธิบาย
Jay Wilde

125
Table1                Table2
_______               _________
1                      2
2                      2
3                      5
4                      6

SELECT Table1.Id, Table2.Id FROM Table1 LEFT OUTER JOIN Table2 ON Table1.Id=Table2.Id

ผล:

1,null
2,2
2,2
3,null
4,null

1
เรียบง่ายและยังทรงพลัง
kiradotee

39

มันเป็นไปไม่ได้ จำนวนระเบียนในตารางด้านซ้ายคือจำนวนระเบียนขั้นต่ำที่จะส่งคืน หากตารางด้านขวามีสองระเบียนที่ตรงกับหนึ่งระเบียนในตารางด้านซ้ายมันจะส่งคืนสองระเบียน


12

ในการตอบสนองต่อ postscript ของคุณนั้นขึ้นอยู่กับสิ่งที่คุณต้องการ

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

อีกทางหนึ่งขึ้นอยู่กับสิ่งที่คุณต้องการจริง ๆ คุณสามารถใช้ฟังก์ชันการรวม (ตัวอย่างเช่นคุณต้องการสตริงจากส่วนด้านขวาคุณสามารถสร้างคอลัมน์ที่เป็นสตริงที่คั่นด้วยเครื่องหมายจุลภาคของผลลัพธ์ด้านขวาสำหรับแถวด้านซ้ายนั้น

หากคุณดูที่คอลัมน์ 1 หรือ 2 คอลัมน์จากการรวมภายนอกคุณอาจลองใช้แบบสอบถามย่อยแบบสเกลาร์เนื่องจากคุณจะรับประกันผล 1 รายการ


4
นี่เป็นคำตอบที่ดีเนื่องจากมีคำแนะนำเกี่ยวกับวิธีการส่งคืนแถวจากตารางด้านซ้าย
karns

9

แต่ละระเบียนจากตารางด้านซ้ายจะถูกส่งกลับหลายครั้งเนื่องจากมีระเบียนที่ตรงกันในตารางด้านขวา - อย่างน้อย 1 แต่อาจมากกว่า 1 ได้อย่างง่ายดาย


8

ซ้ายเข้าร่วมเช่นเดียวกับเข้าร่วมภายใน (เข้าร่วมปกติ) จะกลับมาผลลัพธ์มากสำหรับแต่ละแถวในตารางซ้ายเท่าที่พบในการแข่งขันในตารางด้านขวา ดังนั้นคุณสามารถได้ผลลัพธ์จำนวนมาก - สูงสุด N x M โดยที่ N คือจำนวนแถวในตารางด้านซ้ายและ M คือจำนวนแถวในตารางด้านขวา

เป็นจำนวนผลลัพธ์ขั้นต่ำที่รับประกันใน LEFT OUTER JOIN เป็นอย่างน้อย N เสมอ


1
ฉันเริ่มคิดว่าเมื่อจำนวนแถวเท่ากัน N x M และสถานการณ์จริงเท่านั้นที่อยู่ในใจของฉันคือเมื่อ N หรือ M เท่ากับ 1 คุณเห็นด้วยไหม?
BartoszMiller

2
ไม่ฉันไม่ คุณไม่ควรคิดถึงเงื่อนไขการเข้าร่วมเนื่องจากการเข้าร่วมที่เท่าเทียมกันที่สำคัญเท่านั้น มันอาจเป็นเงื่อนไขโดยพลการเช่นช่วงวันที่ความไม่เท่าเทียมกัน ฯลฯ สองกรณีที่รุนแรง: (a) แถว N ไม่มีการจับคู่เดี่ยวระหว่างแถว M จากนั้นปล่อยให้ผลลัพธ์การรวมภายนอกในแถว N ตรงกับ NULL (b) แถว N ทุกแถวตรงกับแถว M ทั้งหมดผลที่ได้คือชุดแถว N x M
topchef

1
คุณพูดถูกฉันคิดถึงการเข้าร่วมในแง่ของความเท่าเทียมกันเท่านั้น ฉันชอบตัวอย่างของคุณจาก "case b" ฉันเชื่อว่า "ทุกแถว N ตรงกับแถว M ทั้งหมด" เป็นสูตรทั่วไปเมื่อคืนแถว N x M ซึ่งเป็นไปไม่ได้ที่จะเห็นภาพเมื่อคิดเกี่ยวกับความเท่าเทียมกันที่สำคัญเท่านั้น
BartoszMiller

7

มันอาจเป็นความสัมพันธ์แบบหนึ่งต่อหลายอย่างระหว่างตารางด้านซ้ายและขวาใช่ไหม


6

ให้ความสนใจถ้าคุณมีส่วนคำสั่งที่ไหนในตาราง "ด้านขวา" ของแบบสอบถามที่มีการรวมด้านนอกด้านซ้าย ... ในกรณีที่คุณไม่มีบันทึกทางด้านขวาที่ตรงกับส่วนคำสั่งของตำแหน่งแล้วบันทึกที่เกี่ยวข้องของด้านซ้าย ตาราง 'จะไม่ปรากฏในผลการค้นหาของคุณ ....


1
จากนั้นคุณควรเพิ่มเงื่อนไขไปยังส่วนคำสั่ง ON ของ LEU OUTER OOTER JOIN
มิค

6

หากคุณต้องการแถวใดแถวหนึ่งจากด้านขวา

SELECT SuspReason, SiteID FROM(
    SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID, ROW_NUMBER()
    OVER(PARTITION BY SUSP.Susp_Visits.SiteID) AS rn
    FROM SUSP.Susp_Visits
    LEFT OUTER JOIN DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum
) AS t
WHERE rn=1

หรือเพียงแค่

SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID
FROM SUSP.Susp_Visits WHERE EXISTS(
    SELECT DATA.Dim_Member WHERE SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum
)

1
เนื่องจากคุณไม่ได้ให้ DDL และ DML ฉันไม่ได้ทดสอบ อย่างไรก็ตามฉันคิดว่า EXISTS เป็นสิ่งที่คุณต้องการ ลองสิ่งนี้: SELECT SuspReason, SiteID FROM (SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID, ROW_NUMBER () ขึ้นไป (พาร์ติชันโดย SUSP.Susp_Visits.SiteID) ตาม rn SUSP.Susp_VisitsSiteID เข้าร่วม Data.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum) ตามที่ rn = 1
AK


2

หากแถว (x) หลายแถวใน Dim_Member เชื่อมโยงกับแถวเดียวใน Susp_Visits จะมีแถว x แถวในชุด resul

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