Lekce 2.2

SQL v praxi

Výběr, filtrování a řazení dat, vkládání, úpravy a mazání záznamů, potom JOINy včetně rozdílu LEFT a RIGHT a agregace – vše nad připravenou databází e-shopu.

Spojování tabulek

Data jsme rozdělili do tabulek, aby se nic neopakovalo. Když je ale chceme vidět pohromadě, musíme je v dotazu zase spojit.

sql
SELECT id, customer_id, created_at
FROM orders
WHERE id = 103;

Objednávka 103 patří zákazníkovi 3. Jenže kdo to je? Jméno v tabulce orders není, leží v customers. Potřebujeme dotaz, který si ho tam dohledá sám.

JOIN

sql
SELECT orders.id, orders.created_at, customers.name
FROM orders
JOIN customers ON orders.customer_id = customers.id;

JOIN připojí k tabulce z FROM druhou tabulku a ON říká, které řádky k sobě patří. Skoro vždycky je to cizí klíč rovná se primárnímu klíči. Pro každou objednávku databáze najde zákazníka, jehož id se shoduje s customer_id, a z obou řádků složí jeden.

Sloupec id mají obě tabulky, proto před názvy sloupců píšeme tabulku. Aby se to dalo číst, dávají se tabulkám krátké přezdívky, tzv. aliasy:

sql
SELECT o.id, o.created_at, c.name
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE c.email = 'matej.dvorak@example.cz';

Spojit jde i víc tabulek za sebou. Vazbu M:N mezi objednávkami a produkty z minulé lekce rozkládá spojovací tabulka na dvě vazby 1:N, a tak potřebujeme dva JOINy:

sql
SELECT p.name, oi.quantity, oi.price
FROM order_items oi
JOIN products p ON oi.product_id = p.id
WHERE oi.order_id = 110;
sql
-- obsah objednávky i se jménem zákazníka
SELECT c.name, p.name, oi.quantity
FROM orders o
JOIN customers c ON o.customer_id = c.id
JOIN order_items oi ON oi.order_id = o.id
JOIN products p ON oi.product_id = p.id
WHERE o.id = 110;

LEFT JOIN

Obyčejný JOIN (celým jménem INNER JOIN) vrátí jen řádky, které mají protějšek v obou tabulkách. Zákazníci bez objednávek z výsledku tiše zmizí. Jak potom zjistíme, kdo zatím nic neobjednal?

sql
SELECT c.name, o.id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id;

LEFT JOIN vrátí všechny řádky levé tabulky, té z FROM. Kde protějšek chybí, doplní do sloupců pravé tabulky NULL. Zákazníci bez objednávek tak ve výsledku zůstanou a mají o.id prázdné. Stačí je odfiltrovat podmínkou WHERE o.id IS NULL.

Představme si učitele s třídním seznamem a hromádkou odevzdaných úkolů. Obyčejný JOIN je seznam úkolů se jmény autorů: kdo neodevzdal, na něm není. LEFT JOIN je celý třídní seznam, kde u některých jmen místo úkolu stojí pomlčka.

RIGHT JOIN

RIGHT JOIN dělá totéž z druhé strany: vrátí všechny řádky pravé tabulky, té za JOIN. Stejný výsledek jako výš dostaneme, když tabulky prohodíme:

sql
SELECT c.name, o.id
FROM orders o
RIGHT JOIN customers c ON o.customer_id = c.id;

Každý RIGHT JOIN jde tedy přepsat na LEFT JOIN prohozením tabulek. Osobně si myslím, že LEFT JOIN se čte lépe, protože tabulka, ze které chceme všechny řádky, stojí hned na začátku za FROM. Proto se v praxi potkáte hlavně s ním. SQLite navíc RIGHT JOIN umí teprve od roku 2022, takže ho starší nástroje neznají.

Bonus

Spusťte spojení tabulek orders a customers bez části ON. Kolik řádků vyjde a jak to číslo souvisí s počtem objednávek a zákazníků? Dohledejte si, co je kartézský součin.