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
PHP Ferrari
źródło
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 
RedFilter
źródło
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
PHP Ferrari
źródło
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
Ali Umair
źródło
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.

sameerNAT
źródło
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
Manish
źródło
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);
user3477784
źródło
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ę !!!

Dracula Oppa
źródło