MySQL Tahák

Vztahy mezi tabulkami

Tato stránka popisuje tři typy vztahů mezi tabulkami. Kromě toho jsem tu hlavně ještě zařadil spojování tabulek při získávání jejich položek.

Typy vztahů mezi tabulkami

ONE TO ONE

Vztah ONE TO ONE se moc často nepoužívá. Jde o vztah jen mezi dvěmi položkami. Mohli bychom mít například jednu tabulku pro uživatele a druhou tabulku pro více informací o uživatelích. Každý uživatel v první tabulce by měl jednu položku v tabulce s více informacemi. Možná bychom si ale vystačili jen s jednou tabulkou, proto se vztah ONE TO ONE tolik nepoužívá.

ONE TO MANY

Vztah ONE TO MANY se týká jedné položky a více položek odkazujících na ni. Mohli bychom například mít tabulku s knihami a každá kniha by mohla mít více hodnocení z tabulky s hodnoceními knih (mohlo by být více hodnoceních odkazujících na jednu knihu).

MANY TO MANY

Vztah MANY TO MANY si můžeme představit například u tabulky s knihami a u tabulky s jejími autory. Kniha může mít více autorů a ti zase mohou mít více knih.

Spojování tabulek při získávání položek z databáze

Při získávání položek z databáze k sobě můžeme více tabulek spojit dohromady. Existují různé typy spojování tabulek (JOINS). Dále v textu jsou popsány.

CROSS JOIN

Tento typ spojení tabulek je nejjednodušší a pravděpodobně i zbytečný. Cross join se vytvoří když se jen tak pokusíme získat položky z více tabulek najednou. Tabulky se k sobě jen tak připojí bez žádné logiky. Pokud je nějaká tabulka kratší než druhá, tak se bude duplikovat její poslední položka.

SELECT * FROM users, comments; # tabulky se spojí dohromady (bez žádné logiky)

INNER JOIN

Tento typ spojení tabulek vznikne, když při získávání položek z více tabulek použijeme podmínku pomocí WHERE. Pokud máme v tabulkách sloupce, které se jmenují stejně, tak pokud je budeme v této podmínce používat, musíme specifikovat které tabulce sloupec patří připsáním jména tabulky a tečky před název sloupce. Je to dobré takto dělat i když sloupce nejsou stejné. Jednoduše se k sobě připojí položky, které splní podmínku (některé hodnoty tam ale mohou být vícekrát, spojí se vícekrát).

# sloučení tabulek customers a orders podle podmínky
SELECT * FROM customers, orders
WHERE customers.id = orders.customer_id;

Použitím podmínky s pomocí WHERE se INNER JOIN vytvoří implicitně. Je ale lepší jej vytvářet explicitně pomocí JOIN. Použijeme jej tak že použijeme SELECT jen na jednu tabulku a za tento příkaz napíšeme text 'JOIN', tabulku se kterou chceme tabulku spojit, text 'ON' a podmínku, která musí platit aby se položky spojili.

SELECT * FROM customers
JOIN orders
    ON customers.id = orders.customer_id; # podmínka, která musí platit aby se položky sloučili dohromady

V předchozím příkladu jsme použili jen slovo 'JOIN', pokud bychom ale před něj zapsali ještě slovo 'INNER', bylo by to úplně stejné.

LEFT JOIN

Tento typ spojení vezme vše z jedné tabulky a popřípadě k tomu připojí něco z druhé tabulky. LEFT JOIN vytvoříme stejně jako INNER JOIN, jen před slovo 'JOIN' připíšeme slovo 'LEFT'. Pokud se pro nějakou položku v první tabulce nenajde nic v druhé tabulce, tak se pro vyplnění sloupců z druhé tabulky použije NULL.

# vezme vše z tabulky customers a popřípadě k tomu připojí něco z tabulky orders
SELECT * FROM customers
LEFT JOIN orders
    ON customers.id = orders.customer_id;

RIGHT JOIN

Tento typ spojení vezme vše z druhé tabulky a popřípadě k tomu připojí něco z první tabulky. Pokud se pro nějakou položku v druhé tabulce nenajde nic v první tabulce, tak se pro vyplnění sloupců z první tabulky použije NULL.

# vezme vše z tabulky orders a popřípadě k tomu připojí něco z tabulky customers
SELECT * FROM customers
RIGHT JOIN orders
    ON customers.id = orders.customer_id;

Řetězení spojování tabulek

Spojování tabulek můžeme řetězit zapsáním dalšího JOIN za JOIN. Ukazuje to následující ukázka.

SELECT title, rating, CONCAT(first_name, ' ', last_name) AS reviewer
FROM reviews
LEFT JOIN series # sloučení tabulek reviews a series
    ON series.id = reviews.series_id
LEFT JOIN reviewers # použití JOIN na sloučenou tabulku
    ON reviewers.id = reviews.reviewer_id;