MySQL: การแบ่งประเภทของการรวมอย่างรวดเร็ว


157

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

  • คั่นด้วยเครื่องหมายจุลภาค (สิ่งที่ว่าเป็นระยะสั้นนี้?):SELECT * FROM a, b WHERE b.id = a.beeId AND ...
  • แสดงข้อมูลจาก a แม้ว่าจะไม่มีการจับคู่ใน b: SELECT * FROM a LEFT OUTER JOIN b ON b.id = a.beeId WHERE ...

ฉันเคยเห็นผู้เข้าร่วมคนอื่น ๆ แต่ต้องการรู้ว่าอะไรที่ทำให้พวกเขาแตกต่างคืออะไรINNER/ OUTERเพิ่มการLEFTเปลี่ยนแปลงอะไร

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


คำตอบ:


463

3
+1 แต่ทั้งคู่หายไปcross joinซึ่งเป็นผลิตภัณฑ์คาร์ทีเซียน
เดนิสเดอเบอร์นาดี

11
@denis: ดูอย่างใกล้ชิดในลิงค์ codinghorror.com:There's also a cartesian product or cross join, which as far as I can tell, can't be expressed as a Venn diagram:
Rufinus

1
ฉันประหลาดใจที่พิมพ์ไดอะแกรมและวางลงบนผนังสำนักงานของฉัน คุณเปลี่ยนชีวิตฉัน!
yossico

41
คำถามเกี่ยวกับ MySQL โดยเฉพาะ MySQL ไม่รองรับ FULL OUTER
Mike Baranczak

4
และแน่นอนว่านี่ควรเป็นเหตุผลที่จะไม่โพสต์กราฟิคนี้ ถอนหายใจ
Rufinus

27

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

  • เข้าร่วม: กลับแถวเมื่อมีอย่างน้อยหนึ่งการแข่งขันในทั้งสองตาราง
  • เข้าร่วมซ้าย: กลับแถวทั้งหมดจากตารางด้านซ้ายแม้ว่าจะไม่มีการแข่งขันในตารางด้านขวา
  • เข้าร่วมขวา: กลับแถวทั้งหมดจากตารางด้านขวาแม้ว่าจะไม่มีการแข่งขันในตารางด้านซ้าย
  • เข้าร่วมเต็มรูปแบบ: กลับแถวเมื่อมีการแข่งขันในหนึ่งในตาราง

สิ้นสุดการแก้ไข

สรุปตัวอย่างที่คั่นด้วยเครื่องหมายจุลภาคที่คุณให้ไว้

SELECT * FROM a, b WHERE b.id = a.beeId AND ...

กำลังเลือกทุกระเบียนจากตาราง a และ b ด้วยเครื่องหมายจุลภาคคั่นตารางซึ่งสามารถใช้ในคอลัมน์เช่นนี้ได้เช่นกัน

SELECT a.beeName,b.* FROM a, b WHERE b.id = a.beeId AND ...

จากนั้นจะได้รับข้อมูลที่แนะนำในแถวที่คอลัมน์ b.id และคอลัมน์ a.beeId มีคู่ที่ตรงกันในตัวอย่างของคุณ ดังนั้นในตัวอย่างของคุณมันจะได้รับข้อมูลทั้งหมดจากตาราง a และ b โดยที่ b.id เท่ากับ a.beeId ในตัวอย่างของฉันมันจะได้รับข้อมูลทั้งหมดจากตาราง b และข้อมูลเฉพาะจากคอลัมน์ a.beeName เมื่อ b.id เท่ากับ a.beeId โปรดทราบว่ามีคำสั่งย่อย AND ซึ่งจะช่วยในการปรับแต่งผลลัพธ์ของคุณ

สำหรับบทเรียนและคำอธิบายง่ายๆเกี่ยวกับการรวม mySQL และการเข้าร่วมด้านซ้ายดูที่บททดสอบ mySQL ของ Tizag คุณสามารถตรวจสอบเว็บไซต์ของ Keith J. Brownเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับการเข้าร่วมที่ค่อนข้างดี

ฉันหวังว่านี่จะช่วยคุณได้


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

ข้อมูลอ้างอิงอื่นในคำตอบ ... อาจเป็นสิ่งที่คุณต้องการเพิ่มเติม
Ryan

+1 สำหรับการแก้ไขนั้น ฉันไม่ได้ลำเอียงกับ W3Schools อย่างที่บางคนดูเหมือนจะเป็น บางทีฉันไม่เคยเห็นด้านเลวหรือบางทีอาจเป็นเพียง "สงครามศักดิ์สิทธิ์" นอกจากนี้ฉันแก้ไขในเนื้อหาจาก W3Schools ฉันหวังว่าคุณจะไม่รังเกียจ แต่รู้สึกฟรีเพื่อแก้ไขสิ่งที่คุณต้องการ ภาพเหล่านั้นทั้งหมดในคำตอบที่ได้รับการยอมรับเป็นสิ่งที่ดี แต่จริงๆแล้วมีบางรูปแบบของการเข้าร่วมที่เหมือนกัน นี่เป็นทางเลือกที่ดี
ไบรอันฟิลด์

ขอบคุณจอร์จฉันไม่รังเกียจเลยการแก้ไขให้ถูกต้อง! ฉันเชื่อว่าผู้คนจำเป็นต้องค้นหาแหล่งที่เหมาะสมสำหรับพวกเขาข้อมูลมากหรือน้อยตัวอย่างจำนวนมากหรือไม่มีเลย W3 โรงเรียนมีความถูกต้องและรัดกุมพวกเขามักจะมีตัวอย่างที่ดีเช่นกัน Tizag ก็คล้ายกัน หาคู่ง่าย ๆ
Ryan

1
ไม่มีการเข้าร่วมเต็มรูปแบบใน mysql ดังนั้นลิงก์เหล่านี้จึงไม่ค่อยมีประโยชน์
อีเธอร์

13

ฉันมี 2 ตารางเช่นนี้

> SELECT * FROM table_a;
+------+------+
| id   | name |
+------+------+
|    1 | row1 |
|    2 | row2 |
+------+------+

> SELECT * FROM table_b;
+------+------+------+
| id   | name | aid  |
+------+------+------+
|    3 | row3 |    1 |
|    4 | row4 |    1 |
|    5 | row5 | NULL |
+------+------+------+

INNER JOIN ใส่ใจทั้งสองตาราง

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

> SELECT * FROM table_a a INNER JOIN table_b b ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | id   | name | aid  |
+------+------+------+------+------+
|    1 | row1 |    3 | row3 | 1    |
|    1 | row1 |    4 | row4 | 1    |
+------+------+------+------+------+

มันไม่ได้ทำให้ความแตกต่างกับ INNER JOIN ถ้าคุณกลับคำสั่งซื้อเพราะมันใส่ใจทั้งสองตาราง:

> SELECT * FROM table_b b INNER JOIN table_a a ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | aid  | id   | name |
+------+------+------+------+------+
|    3 | row3 | 1    |    1 | row1 |
|    4 | row4 | 1    |    1 | row1 |
+------+------+------+------+------+

คุณได้รับแถวเดียวกัน แต่คอลัมน์อยู่ในลำดับที่แตกต่างกันเพราะเราพูดถึงตารางในลำดับที่แตกต่างกัน

ซ้ายเข้าร่วมเพียงใส่ใจเกี่ยวกับตารางแรก

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

> SELECT * FROM table_a a LEFT JOIN table_b b ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | id   | name | aid  |
+------+------+------+------+------+
|    1 | row1 |    3 | row3 | 1    |
|    1 | row1 |    4 | row4 | 1    |
|    2 | row2 | NULL | NULL | NULL |
+------+------+------+------+------+

ด้านบนคุณสามารถเห็นทุกแถวของ table_a แม้ว่าบางคนไม่ตรงกับสิ่งใดในตาราง b แต่ไม่ใช่ทุกแถวของ table_b - เฉพาะแถวที่ตรงกับบางอย่างใน table_a

หากเรากลับลำดับของตาราง LEFT JOIN จะทำงานแตกต่างกัน:

> SELECT * FROM table_b b LEFT JOIN table_a a ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | aid  | id   | name |
+------+------+------+------+------+
|    3 | row3 | 1    |    1 | row1 |
|    4 | row4 | 1    |    1 | row1 |
|    5 | row5 | NULL | NULL | NULL |
+------+------+------+------+------+

ตอนนี้เราได้รับ table_b ทุกแถว แต่จะจับคู่เฉพาะแถวของ table_a เท่านั้น

RIGHT JOIN สนใจเฉพาะโต๊ะที่สองเท่านั้น

a RIGHT JOIN bทำให้คุณเหมือนกันb LEFT JOIN aทุกประการ ความแตกต่างเพียงอย่างเดียวคือลำดับเริ่มต้นของคอลัมน์

> SELECT * FROM table_a a RIGHT JOIN table_b b ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | id   | name | aid  |
+------+------+------+------+------+
|    1 | row1 |    3 | row3 | 1    |
|    1 | row1 |    4 | row4 | 1    |
| NULL | NULL |    5 | row5 | NULL |
+------+------+------+------+------+

นี่คือแถวเดียวกับtable_b LEFT JOIN table_aที่เราเห็นในส่วนซ้ายเข้าร่วม

ในทำนองเดียวกัน:

> SELECT * FROM table_b b RIGHT JOIN table_a a ON a.id=b.aid;
+------+------+------+------+------+
| id   | name | aid  | id   | name |
+------+------+------+------+------+
|    3 | row3 | 1    |    1 | row1 |
|    4 | row4 | 1    |    1 | row1 |
| NULL | NULL | NULL |    2 | row2 |
+------+------+------+------+------+

table_a LEFT JOIN table_bเป็นแถวเดียวกับ

ไม่มีการเข้าร่วมเลยให้สำเนาของทุกอย่าง

No Join clause: หากคุณเขียนตารางโดยไม่มี JOIN clause เลยเพียงแค่คั่นด้วยเครื่องหมายจุลภาคคุณจะได้รับทุกแถวของตารางแรกที่เขียนถัดจากทุกแถวของตารางที่สองในชุดค่าผสมที่เป็นไปได้ทั้งหมด:

> SELECT * FROM table_b, table_a;        
+------+------+------+------+------+
| id   | name | aid  | id   | name |
+------+------+------+------+------+
|    3 | row3 | 1    |    1 | row1 |
|    3 | row3 | 1    |    2 | row2 |
|    4 | row4 | 1    |    1 | row1 |
|    4 | row4 | 1    |    2 | row2 |
|    5 | row5 | NULL |    1 | row1 |
|    5 | row5 | NULL |    2 | row2 |
+------+------+------+------+------+

(นี่คือจากโพสต์บล็อกของฉันตัวอย่างของประเภทการเข้าร่วม SQL )


@Anu โปรดอย่าแก้ไขสิ่งเล็กน้อยเมื่อชื่อเสียงที่ต่ำของคุณหมายความว่าการแก้ไขของคุณจะต้องได้รับการตรวจสอบโดยผู้อื่นคุณเพียงแค่เสียเวลา การแก้ไขนั้นควรถูกปฏิเสธว่าไม่มีความแตกต่าง รหัสที่คุณเปลี่ยนไม่ได้ผิดจริง & คุณสามารถแสดงความคิดเห็นได้
philipxy

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

@Anu คำตอบนี้มีคำอธิบายที่ไม่สมบูรณ์ที่กระจัดกระจายเหมือนกับคำตอบส่วนใหญ่ ไม่ได้บอกว่าเอาต์พุตเป็นฟังก์ชั่นของอินพุตอะไร ดูคำตอบเกือบทุกข้อที่มีการเสนอซ้ำและความคิดเห็นของฉันในทั้งสองหน้า ดูคำตอบของฉันที่นั่นด้วย PS I coincientally เพิ่งเห็นเมื่อวานนี้จากอีกคนประเมินขนาดแก้ไข (แน่นอนมีหลายบทความที่เกี่ยวข้องเพิ่มเติมได้ที่Meta กองมากเกินและMeta Stack แลกเปลี่ยน .)
philipxy

11

Full outer join ไม่มีอยู่ใน mysql คุณอาจต้องใช้การรวมกันของซ้ายและขวา

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