Dołączenie do trzech tabel za pomocą MySQL


117

Mam trzy nazwane tabele

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

Teraz, aby pokazać nazwisko ucznia wraz z nazwą kursu, który studiował,

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

Buduję następujące zapytanie

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

Ale nie zwraca wymaganego wyniku ...

A co by było dla znormalizowanej formy, jeśli chcę dowiedzieć się, kto jest menedżerem nad innymi:

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

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

I chce uzyskać ten wynik:

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

w pierwszym wyniku błędnie ustawiłeś dane dla ahmed i ali
NineCattoRules

Odpowiedzi:



199

Użyj składni ANSI, a sposób dołączania do tabel będzie o wiele bardziej jasny:

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: Nasze odpowiedzi są takie same, różnią się tylko składnią. Jeśli nie jesteś świadomy ANSIskładni, warto poświęcić czas na jej naukę. Pomoże Ci to uniknąć JOINbłędów, jakie popełniłeś w przyszłości.
RedFilter

16

Forma normalizacji

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

Czy kolejność ma znaczenie w m.mid = e1.idi m.eid = e2.id?
Pathros

1
@Pathros Nie, w tych wyrażeniach porządek nie ma znaczenia.
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

Ta odpowiedź wygląda bardzo podobnie do odpowiedzi udzielonych już 5 lat wcześniej. Co z twoją odpowiedzią uważasz za ważną i brakuje jej w istniejących odpowiedziach?
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;

Możesz DOŁĄCZAĆ do wielu TABEL, tak jak w powyższym przykładzie.


Istnieje już wiele odpowiedzi, sprzed lat, które pokazują „dołączanie do wielu stołów”. Co twoja odpowiedź wnosi do dyskusji?
ToolmakerSteve

0

Zapytanie o dołączenie do więcej niż dwóch tabel:

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

Istnieje już wiele odpowiedzi, sprzed lat, które pokazują „dołączanie do wielu stołów”. Co twoja odpowiedź wnosi do dyskusji?
ToolmakerSteve

0

Użyj tego:

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
Ta odpowiedź nie dodaje nic nowego do tego pytania i używa dziwnej (jeśli nie zwykłej złej składni, zdziwiłbym się, gdyby było to poprawne w MySQL).
AeroX

Nie zgadzam się z AeroX. Składnia złączenia Ansi ma na celu ujednoznacznienie problemów ze składnią przecinka / where starej szkoły. Chcę sprawdzić, czy MySql obsługuje w szczególności składnię sprzężenia ansi.
Larry Smith

0

Nie dołączaj w ten sposób. To naprawdę bardzo zła praktyka !!! Spowolni to wydajność pobierania z ogromnymi danymi. Na przykład, jeśli w każdej tabeli było 100 wierszy, serwer bazy danych musi pobrać 100x100x100 = 1000000czasy. Musiał przybierać na wiele 1 millionrazy. Aby przezwyciężyć ten problem, dołącz do pierwszych dwóch tabel, które mogą pobierać, aby uzyskać minimalne możliwe dopasowanie (zależy to od schematu bazy danych). Użyj tego wyniku w Subquery, a następnie połącz go z trzecią tabelą i pobierz. Za pierwsze złączenie -> 100x100= 10000razy i przypuśćmy, że otrzymamy 5 pasujących wyników. A potem dołączamy do trzeciej tabeli z wynikiem -> 5x100 = 500.Całkowite pobranie = 10000+500 = 10200tylko razy. I tak wydajność poszła w górę !!!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.