V tabulce známek je jen číslo žáka, třeba 2. Učitelka ale chce vidět „Petr – M – 3“, ne „2 – M – 3“. Jméno je v jiné tabulce. Musí obě tabulky „slepit“ podle čísla žáka.
Kvůli normalizaci jsou data rozdělená do více tabulek. Při čtení je zase skládáme dohromady. Na to slouží spojování tabulek, anglicky JOIN. Je to nejdůležitější dovednost práce s SQL.
zaci.id). Cizí klíč na něj odkazuje z jiné tabulky (znamky.id_zaka).Známka s id_zaka = 2 patří žákovi s id = 2.JOIN … ON …Ke každému řádku jedné tabulky připojí řádky druhé tabulky, pro které platí podmínka za ON. Podmínka obvykle porovná cizí klíč s primárním.zaci JOIN znamky ON zaci.id = znamky.id_zakaINNER JOINVrátí jen dvojice řádků, které k sobě našly protějšek. Slovo INNER se smí vynechat, samotné JOIN znamená totéž.Žák bez známek ve výsledku nebude.alias.sloupec.FROM zaci z → z.jmeno| id | jmeno | trida |
|---|---|---|
| 1 | Eva | 2.A |
| 2 | Petr | 2.A |
| 3 | Jana | 3.B |
| 4 | Tomáš | 3.B |
| 5 | Lucie | 1.C |
| id | id_zaka | predmet | znamka |
|---|---|---|---|
| 1 | 1 | M | 1 |
| 2 | 1 | ČJ | 2 |
| 3 | 2 | M | 3 |
| 4 | 2 | ČJ | 4 |
| 5 | 3 | M | 2 |
| 6 | 4 | ČJ | 1 |
| 7 | 2 | M | 5 |
SELECT z.jmeno, k.predmet, k.znamkaFROM zaci zJOIN znamky k ON z.id = k.id_zakaWHERE z.trida = '2.A';k.id_zaka = z.id.WHERE nechá jen žáky z 2.A.SELECT * FROM zaci z JOIN znamky k ON z.id = k.id_zaka; (bez WHERE)?SELECT z.jmeno, AVG(k.znamka) FROM zaci z JOIN znamky k ON z.id = k.id_zaka GROUP BY z.id, z.jmeno; Nejdřív spojení, pak seskupení. Výsledek: Eva 1.5, Petr 4, Jana 2, Tomáš 1.SELECT jmeno, znamka FROM zaci, znamky;SELECT jmeno, znamka FROM zaci JOIN znamky ON zaci.id = znamky.id_zaka;Bez podmínky spojení se každý žák spojí s každou známkou (5 · 7 = 35 řádků). Většina dvojic nedává smysl.
JOIN … ON spojí řádky dvou tabulek podle podmínky, nejčastěji cizí klíč = primární klíč. Vnitřní spojení vrátí jen řádky, které mají protějšek. Aliasy (zaci z) zkracují zápis.Učitelka chce seznam všech žáků se známkami. I Lucii, která zatím žádnou známku nemá, aby nezapomněla ji vyzkoušet. Obyčejné JOIN by Lucii vynechalo. Pro takové případy existují vnější spojení.
Druhy spojení si nejlépe představíš jako dvě překrývající se množiny: žáky a známky. Každý druh spojení vybere jinou část.
ON, obvykle cizí klíč = primární klíč.zaci z JOIN znamky k ON z.id = k.id_zakaJOIN, pravá za ním.V zaci LEFT JOIN znamky je levá zaci.OUTER se smí vynechat.Lucie se ve výsledku objeví se známkou NULL.| Spojení | Co vrátí | Pro žáky a známky |
|---|---|---|
INNER JOIN | jen řádky s protějškem | 7 řádků, Lucie chybí |
LEFT JOIN | všechny řádky levé tabulky + protějšky (nebo NULL) | 8 řádků, Lucie s NULL |
RIGHT JOIN | všechny řádky pravé tabulky + protějšky (nebo NULL) | jako LEFT, jen strany obráceně |
FULL OUTER JOIN | všechny řádky obou tabulek | nepodporuje např. MySQL |
CROSS JOIN | každý s každým | 35 řádků |
Roztřiď úlohy: stačí vnitřní spojení, nebo potřebuješ i řádky bez protějšku?
SELECT z.jmenoFROM zaci zLEFT JOIN znamky k ON z.id = k.id_zakaWHERE k.id IS NULL;LEFT JOIN ponechá všechny žáky. U Lucie nenašel žádnou známku, proto jsou sloupce známek NULL. WHERE k.id IS NULL nechá právě takové žáky. Výsledek: Lucie.
SELECT * FROM zaci z LEFT JOIN znamky k ON z.id = k.id_zaka;?zaci, zak_krouzek(id_zaka, id_krouzku) a krouzky(id, nazev). Vypiš jména žáků a názvy kroužků.SELECT z.jmeno, kr.nazev FROM zaci z JOIN zak_krouzek zk ON z.id = zk.id_zaka JOIN krouzky kr ON kr.id = zk.id_krouzku; Vazební tabulka je uprostřed, na každé straně jedno JOIN.… LEFT JOIN znamky k ON z.id = k.id_zaka WHERE k.predmet = 'M' vrátí všechny žáky.ON: ON z.id = k.id_zaka AND k.predmet = 'M'.U žáků bez známky z M je k.predmet NULL a podmínka ve WHERE je vyřadí. Z LEFT JOIN se tak nechtěně stane vnitřní spojení.
INNER JOIN vrátí jen řádky s protějškem, LEFT JOIN všechny řádky levé tabulky (chybějící doplní NULL), RIGHT JOIN pravé, FULL OUTER JOIN obou. CROSS JOIN spojí každý řádek s každým.