ลำดับการเข้าร่วมมีความสำคัญใน SQL หรือไม่


189

หากไม่คำนึงถึงประสิทธิภาพฉันจะได้รับผลลัพธ์เดียวกันจากข้อความค้นหา A และ B ด้านล่างหรือไม่ แล้ว C และ D ล่ะ?

-- A
select *
from   a left join b
           on <blahblah>
       left join c
           on <blahblan>


-- B
select *
from   a left join c
           on <blahblah>
       left join b
           on <blahblan>  

-- C
select *
from   a join b
           on <blahblah>
       join c
           on <blahblan>


-- D
select *
from   a join c
           on <blahblah>
       join b
           on <blahblan>  

11
อะไรนะ<blahblah>? คุณเข้าร่วม A ถึง B และ A ถึง C หรือคุณเข้าร่วม A ถึง B และ B ถึง C หรือไม่
beny23

2
สวัสดี Beny รหัสในคำถามของฉันคือสิ่งที่เป็นนามธรรม ฉันไม่ได้กังวลเกี่ยวกับการเข้าร่วม A ถึง B หรือ A ถึง C ฉันแค่อยากรู้ว่าไวยากรณ์แบบนี้จะให้ผลลัพธ์ที่เหมือนกันหรือไม่
แค่ผู้เรียน

คำตอบ:


225

สำหรับการINNERเข้าร่วมคำสั่งไม่สำคัญ แบบสอบถามจะให้ผลลัพธ์เดียวกันตราบใดที่คุณเลือกเปลี่ยนคุณจากไปSELECT *SELECT a.*, b.*, c.*


สำหรับ ( LEFT, RIGHTหรือFULL) OUTERร่วมใช่เรื่องการสั่งซื้อ - และ ( การปรับปรุง ) สิ่งที่มีความซับซ้อนมากขึ้น

ครั้งแรกการรวมภายนอกไม่ได้สลับกันดังนั้นจึงa LEFT JOIN bไม่เหมือนกับb LEFT JOIN a

การรวมภายนอกไม่เชื่อมโยงกันดังนั้นในตัวอย่างของคุณที่เกี่ยวข้องกับคุณสมบัติทั้งสอง (การสับเปลี่ยนและการเชื่อมโยง)

a LEFT JOIN b 
    ON b.ab_id = a.ab_id
  LEFT JOIN c
    ON c.ac_id = a.ac_id

เทียบเท่ากับ :

a LEFT JOIN c 
    ON c.ac_id = a.ac_id
  LEFT JOIN b
    ON b.ab_id = a.ab_id

แต่:

a LEFT JOIN b 
    ON  b.ab_id = a.ab_id
  LEFT JOIN c
    ON  c.ac_id = a.ac_id
    AND c.bc_id = b.bc_id

ไม่เท่ากับ :

a LEFT JOIN c 
    ON  c.ac_id = a.ac_id
  LEFT JOIN b
    ON  b.ab_id = a.ab_id
    AND b.bc_id = c.bc_id

อีกตัวอย่างการเชื่อมโยง (หวังว่าง่ายกว่า) คิดว่านี่เป็น(a LEFT JOIN b) LEFT JOIN c:

a LEFT JOIN b 
    ON b.ab_id = a.ab_id          -- AB condition
 LEFT JOIN c
    ON c.bc_id = b.bc_id          -- BC condition

นี่เทียบเท่ากับa LEFT JOIN (b LEFT JOIN c):

a LEFT JOIN  
    b LEFT JOIN c
        ON c.bc_id = b.bc_id          -- BC condition
    ON b.ab_id = a.ab_id          -- AB condition

เพียงเพราะเรามีONเงื่อนไข"ดี" ทั้งON b.ab_id = a.ab_idและc.bc_id = b.bc_idเป็นการตรวจสอบความเท่าเทียมกันและไม่เกี่ยวข้องกับNULLการเปรียบเทียบ

คุณสามารถมีเงื่อนไขกับตัวดำเนินการอื่น ๆ หรือสิ่งที่ซับซ้อนกว่าเช่น: ON a.x <= b.xหรือON a.x = 7หรือON a.x LIKE b.xหรือON (a.x, a.y) = (b.x, b.y)และทั้งสองแบบสอบถามจะยังคงเทียบเท่า

อย่างไรก็ตามถ้าเกี่ยวข้องIS NULLหรือฟังก์ชันใด ๆที่เกี่ยวข้องกับโมฆะCOALESCE()เช่นถ้าเงื่อนไขเป็นb.ab_id IS NULLแล้วแบบสอบถามทั้งสองจะไม่เทียบเท่า


3
ถูกต้องมากกว่าที่จะบอกว่าการรวมภายนอกนั้นเชื่อมโยงกันตราบใดที่การสรุปไม่สามารถทำได้โดยแถวที่คอลัมน์ทั้งหมดจากตารางหนึ่งเป็น NULL แทนที่จะบอกว่ามันเชื่อมโยงกันตราบใดที่เพรดิเคตไม่เกี่ยวข้องกับ IS NULL หรือ 'ฟังก์ชั่นที่เกี่ยวข้องกับโมฆะ' เราสามารถจินตนาการได้ว่าคำกริยาที่ตอบสนองคำอธิบายเดิม แต่ไม่ใช่อย่างหลังเช่นa.somecol > 0 OR b.someothercol > 0; การเชื่อมโยงอาจล้มเหลวสำหรับเงื่อนไขนั้น
Mark Amery

แต่ใช่ผมคิดว่ามันเป็นความจริงในทางเทคนิคที่จะบอกว่า OUTER JOIN คือเชื่อมโยงตราบใดที่คำกริยาไม่พอใจอย่างใดอย่างหนึ่งของเงื่อนไขที่ผมอธิบายที่นี่: stackoverflow.com/questions/20022196/... (ครั้งแรกซึ่งยังแบ่งการเชื่อมโยงกัน สำหรับผู้เข้าร่วมภายใน แต่เป็นวิธีการที่ถูกและชัดเจนในการทำลายซึ่งอาจไม่คุ้มค่าที่จะกล่าวถึง) นอกจากนี้ยังชี้ให้เห็นว่าการเข้าร่วมที่พบมากที่สุด - การเข้าร่วมในคีย์ต่างประเทศ - ไม่เป็นไปตามเงื่อนไขเหล่านั้น และเป็นสิ่งที่ดีและเชื่อมโยงกัน
Mark Amery

1
@MarkAmery ขอบคุณผมก็มีช่วงเวลาที่ยากโครงสร้างประโยคของฉันในจุดที่ (และฉันได้ upvoted อยู่แล้วว่าคำตอบของคุณ;)
ypercubeᵀᴹ

ypercube ฉันมีและต่อไปนี้INNER JOIN LEFT JOINมันทำงานเช่นนั้นก่อนแบบสอบถามจะFilterระเบียนบนฐานของINNER JOINแล้วจะใช้LEFT JOINกับFilteredบันทึกหรือไม่
มูฮัมหมัดบาบาร์

ในความเป็นจริงชนิดการรวมทั้งหมดเป็นแบบสัมพันธ์ตามที่ระบุโดยมาตรฐาน SQL และตามคำจำกัดความทางคณิตศาสตร์ของการเชื่อมโยง แต่มันไม่ปรากฏความสัมพันธ์เนื่องจากการจัดเรียงวงเล็บต้องย้ายONประโยค (เช่น "เข้าร่วมข้อกำหนด") ไปยังตำแหน่งใหม่ . นี่เป็นเพียงไวยากรณ์ หากคุณใช้สัญลักษณ์พีชคณิตเชิงสัมพันธ์ (ซึ่งข้อมูลจำเพาะการรวมวางไว้ด้านล่างตัวดำเนินการเข้าร่วม) การเชื่อมโยงจะปรากฏชัดเจนยิ่งขึ้น ข้อโต้แย้งของคุณจะปรากฏที่ด้านนอกเข้าร่วมไม่ได้สับเปลี่ยนซึ่งเป็นที่ถูกต้อง
Lukas เอ๊ด

4

สำหรับการเข้าร่วมปกติก็ไม่ได้ TableA join TableBจะสร้างแผนการดำเนินการเช่นเดียวกับTableB join TableA(ดังนั้นตัวอย่าง C และ D ของคุณจะเหมือนกัน)

สำหรับซ้ายและขวารวมเข้าด้วยกัน TableA left Join TableBแตกต่างกว่าTableB left Join TableAแต่เหมือนกันกว่าTableB right Join TableA


4
นี่เป็นเพียงการสลับสับเปลี่ยน แต่ตัวอย่างในคำถามแสดงว่าผู้ถามสนใจในการเชื่อมโยง คำตอบของ ypercube กล่าวถึงทั้งคู่
Mark Amery

2

หากคุณลองเข้าร่วม C ในฟิลด์จาก B ก่อนเข้าร่วม B เช่น:

SELECT A.x, A.y, A.z FROM A 
   INNER JOIN C
       on B.x = C.x
   INNER JOIN b
       on A.x = B.x

การค้นหาของคุณจะล้มเหลวดังนั้นในกรณีนี้การสั่งซื้อจะมีผล


ใช่ถูกต้องคำตอบที่ถูกต้องควรได้รับการแก้ไข
Nir Pengas

-2

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

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

เครื่องมือเพิ่มประสิทธิภาพไม่ได้เลือกลำดับการเข้าร่วมสำหรับการรวมภายนอก มันใช้คำสั่งที่ระบุไว้ในคำสั่ง

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

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