Nối ba bảng bằng MySQL


117

Tôi có ba bảng tên

**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

Bây giờ để hiển thị tên sinh viên với tên khóa học mà anh ta đã học,

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

Tôi tạo truy vấn sau

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

Nhưng nó không trả về kết quả cần thiết ...

Và điều gì sẽ xảy ra cho biểu mẫu chuẩn hóa, nếu tôi muốn tìm ai là người quản lý so với người khác:

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

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

Và muốn nhận được kết quả này:

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

trong kết quả đầu tiên bạn sai thiết lập dữ liệu cho ahmed và ali
NineCattoRules

Câu trả lời:



199

Sử dụng cú pháp ANSI và sẽ rõ ràng hơn rất nhiều về cách bạn tham gia các bảng:

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
@Muhammad: Câu trả lời của chúng tôi giống nhau, chúng chỉ khác nhau về cú pháp. Nếu bạn không biết về ANSIcú pháp, rất đáng để bạn dành thời gian tìm hiểu nó. Nó sẽ giúp bạn tránh những JOINsai sót như bạn đã mắc phải trong tương lai.
RedFilter 14/09/10

16

Đối với biểu mẫu chuẩn hóa

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

Thứ tự có quan trọng trong m.mid = e1.idm.eid = e2.id?
Pathros

1
@Pathros Không, thứ tự không quan trọng, trong những biểu thức đó.
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

Câu trả lời này trông rất giống với câu trả lời đã được đưa ra 5 năm trước đó. Điều gì về câu trả lời của bạn mà bạn cảm thấy là quan trọng và còn thiếu trong các câu trả lời hiện có?
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;

Bạn có thể THAM GIA nhiều BẢNG như ví dụ trên.


Đã có nhiều câu trả lời, từ những năm trước, cho thấy "tham gia nhiều bảng". Câu trả lời của bạn bổ sung thêm điều gì cho cuộc thảo luận?
ToolmakerSteve

0

Truy vấn để tham gia nhiều hơn hai bảng:

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

Đã có nhiều câu trả lời, từ những năm trước, cho thấy "tham gia nhiều bảng". Câu trả lời của bạn bổ sung thêm điều gì cho cuộc thảo luận?
ToolmakerSteve

0

Dùng cái này:

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
Câu trả lời này không bổ sung gì mới cho câu hỏi này và sử dụng lạ (nếu không phải là cú pháp sai rõ ràng, tôi sẽ ngạc nhiên nếu điều này thậm chí còn hợp lệ trong MySQL).
AeroX

Tôi không đồng ý với AeroX. Cú pháp tham gia Ansi có nghĩa là để phân biệt các vấn đề với cú pháp kết hợp dấu phẩy / where cũ. Tôi đang tìm xem liệu MySql có hỗ trợ cụ thể cú pháp tham gia ansi hay không.
Larry Smith

0

Đừng tham gia như vậy. Đó là một thực hành thực sự thực sự tồi tệ !!! Nó sẽ làm chậm hiệu suất tìm nạp với dữ liệu lớn. Ví dụ: nếu có 100 hàng trong mỗi bảng, máy chủ cơ sở dữ liệu phải tìm nạp 100x100x100 = 1000000thời gian. Nó đã phải tìm nạp nhiều 1 millionlần. Để khắc phục sự cố đó, hãy tham gia hai bảng đầu tiên có thể tìm nạp dẫn đến kết quả phù hợp tối thiểu có thể (Tùy thuộc vào lược đồ cơ sở dữ liệu của bạn). Sử dụng kết quả đó trong Truy vấn con và sau đó nối nó với bảng thứ ba và tìm nạp nó. Đối với lần tham gia đầu tiên -> 100x100= 10000lần và giả sử chúng ta nhận được 5 kết quả phù hợp. Và sau đó chúng tôi tham gia bảng thứ ba với kết quả -> 5x100 = 500.Tổng số 10000+500 = 10200lần tìm nạp = lần duy nhất. Và do đó, hiệu suất đã tăng lên !!!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.