การเข้าร่วมสามตารางโดยใช้ MySQL


117

ฉันมีตารางสามชื่อ

**Student Table**
-------------
id    name
-------------
1     ali
2     ahmed
3     john
4     king

**Course Table**
-------------
id    name
-------------
1     physic
2     maths
3     computer
4     chemistry

**Bridge**
-------------
sid    cid
-------------
1     1
1     2
1     3
1     4
2     1
2     2
3     3
3     4
4     1
4     2

ตอนนี้เพื่อแสดงชื่อนักเรียนพร้อมชื่อหลักสูตรที่เขาเคยเรียนเช่น

**Result**
---------------------------
Student        Course
---------------------------
ahmed         physic
ahmed         maths
ahmed         computer
ahmed         chemistry
ali           physic
ali           maths
john          computer
john          chemistry
king          physic
king          maths

ฉันสร้างแบบสอบถามต่อไปนี้

select s.name as Student, c.name as Course from student s, course c join bridge b on c.id = b.cid order by s.name

แต่กลับไม่ได้ผลลัพธ์ที่ต้องการ ...

และจะเป็นอย่างไรสำหรับรูปแบบมาตรฐานถ้าฉันต้องการค้นหาว่าใครเป็นผู้จัดการมากกว่าคนอื่น ๆ :

**employee**
-------------------
id        name
-------------------
1         ali
2         king
3         mak
4         sam
5         jon

**manage**
--------------
mid      eid
--------------
1         2
1         3
3         4
4         5

และต้องการรับผลลัพธ์นี้:

**result**
--------------------
Manager      Staff
--------------------
ali          king
ali          mak
mak          sam
sam          jon

ในผลลัพธ์แรกคุณตั้งค่าข้อมูลสำหรับ ahmed และ ali ผิด
NineCattoRules

คำตอบ:


150

เพียงใช้:

select s.name "Student", c.name "Course"
from student s, bridge b, course c
where b.sid = s.sid and b.cid = c.cid 


1
ดีและเรียบง่าย แต่ FWIW พิจารณาบล็อกต่อไปนี้เกี่ยวกับไวยากรณ์นี้: sqlblog.org/2009/10/08/bad-habits-to-kick-using-old-style-joinsตามที่กล่าวไว้ในstackoverflow.com/a/13476050/ 199364
ToolmakerSteve

199

ใช้ไวยากรณ์ ANSI และจะชัดเจนมากขึ้นว่าคุณเข้าร่วมตารางอย่างไร:

SELECT s.name as Student, c.name as Course 
FROM student s
    INNER JOIN bridge b ON s.id = b.sid
    INNER JOIN course c ON b.cid  = c.id 
ORDER BY s.name 

9
@ มูฮัมมัด: คำตอบของเราเหมือนกันต่างกันแค่ไวยากรณ์ หากคุณไม่ทราบถึงANSIไวยากรณ์คุณควรเสียเวลาในการเรียนรู้ จะช่วยให้คุณหลีกเลี่ยงJOINข้อผิดพลาดเช่นที่คุณเคยทำในอนาคต
RedFilter

16

สำหรับปรับรูปแบบปกติ

select e1.name as 'Manager', e2.name as 'Staff'
from employee e1 
left join manage m on m.mid = e1.id
left join employee e2 on m.eid = e2.id

คำสั่งซื้อมีความสำคัญในm.mid = e1.idและm.eid = e2.idหรือไม่?
Pathros

1
@ พา ธ รอสไม่ลำดับไม่สำคัญในนิพจน์เหล่านั้น
ToolmakerSteve

4
SELECT *
FROM user u
JOIN user_clockits uc ON u.user_id=uc.user_id
JOIN clockits cl ON cl.clockits_id=uc.clockits_id
WHERE user_id = 158

คำตอบนี้ดูคล้ายกับคำตอบที่ให้ไว้เมื่อ 5 ปีก่อนหน้านี้มาก คำตอบของคุณที่คุณรู้สึกว่าสำคัญและขาดหายไปจากคำตอบที่มีอยู่?
ToolmakerSteve

1
SELECT 
employees.id, 
CONCAT(employees.f_name," ",employees.l_name) AS   'Full Name', genders.gender_name AS 'Sex', 
depts.dept_name AS 'Team Name', 
pay_grades.pay_grade_name AS 'Band', 
designations.designation_name AS 'Role' 
FROM employees 
LEFT JOIN genders ON employees.gender_id = genders.id 
LEFT JOIN depts ON employees.dept_id = depts.id 
LEFT JOIN pay_grades ON employees.pay_grade_id = pay_grades.id 
LEFT JOIN designations ON employees.designation_id = designations.id 
ORDER BY employees.id;

คุณสามารถเข้าร่วมได้หลายตารางเหมือนตัวอย่างด้านบนนี้


มีคำตอบหลายคำตอบจากหลายปีก่อนหน้านี้ซึ่งแสดงว่า "การเข้าร่วมหลายตาราง" คำตอบของคุณเพิ่มอะไรในการสนทนา?
ToolmakerSteve

0

คำถามเพื่อเข้าร่วมมากกว่าสองตาราง:

SELECT ops.field_id, ops.option_id, ops.label
FROM engine4_user_fields_maps AS map 
JOIN engine4_user_fields_meta AS meta ON map.`child_id` = meta.field_id
JOIN engine4_user_fields_options AS ops ON map.child_id = ops.field_id 
WHERE map.option_id =39 AND meta.type LIKE 'outcomeresult' LIMIT 0 , 30

มีคำตอบหลายคำตอบจากหลายปีก่อนหน้านี้ซึ่งแสดงว่า "การเข้าร่วมหลายตาราง" คำตอบของคุณเพิ่มอะไรในการสนทนา?
ToolmakerSteve

0

ใช้สิ่งนี้:

SELECT s.name AS Student, c.name AS Course 
FROM student s 
  LEFT JOIN (bridge b CROSS JOIN course c) 
    ON (s.id = b.sid AND b.cid = c.id);

1
คำตอบนี้ไม่ได้เพิ่มอะไรใหม่ให้กับคำถามนี้และใช้แปลก ๆ (ถ้าไม่ใช่ไวยากรณ์ที่ผิดธรรมดาฉันจะแปลกใจถ้าสิ่งนี้ใช้ได้ใน MySQL)
AeroX

ฉันไม่เห็นด้วยกับ AeroX Ansi join syntax หมายถึงการแก้ปัญหาที่เกิดขึ้นกับเครื่องหมายจุลภาคของโรงเรียนเก่า / ที่ join syntax ฉันต้องการดูว่า MySql รองรับไวยากรณ์การเข้าร่วม ansi โดยเฉพาะหรือไม่
Larry Smith

0

อย่าเข้าร่วมเช่นนั้น เป็นการซ้อมที่แย่จริงๆ !!! จะทำให้ประสิทธิภาพในการดึงข้อมูลจำนวนมากช้าลง ตัวอย่างเช่นหากมี 100 แถวในแต่ละตารางเซิร์ฟเวอร์ฐานข้อมูลจะต้องดึงข้อมูล100x100x100 = 1000000ครั้ง มันต้องดึงข้อมูล1 millionหลายครั้ง เพื่อเอาชนะปัญหานั้นให้เข้าร่วมสองตารางแรกที่สามารถดึงผลลัพธ์ในการจับคู่ขั้นต่ำที่เป็นไปได้ (ขึ้นอยู่กับสคีมาฐานข้อมูลของคุณ) ใช้ผลลัพธ์นั้นในการสืบค้นย่อยจากนั้นรวมเข้ากับตารางที่สามแล้วดึงข้อมูล สำหรับการเข้าร่วมครั้งแรก -> 100x100= 10000ครั้งและสมมติว่าเราได้ผลลัพธ์ที่ตรงกัน 5 รายการ จากนั้นเราก็เข้าร่วมตารางที่สามด้วยผลลัพธ์ -> การ5x100 = 500.ดึงข้อมูลทั้งหมด = 10000+500 = 10200ครั้งเท่านั้น ผลงานก็พุ่งปรี๊ด !!!

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