Seznam z poddotazu: IN
Ve 3. lekci jste používali IN se seznamem hodnot: WHERE id IN (1, 3, 5). Seznam ale nemusíte psát ručně, může ho vytvořit poddotaz. Které hry mají aspoň jednu recenzi s pěti hvězdičkami? ID těchto her najdete v tabulce recenze:
SELECT hra_id FROM recenze WHERE hvezdicky = 5;| hra_id |
|---|
| 1 |
| 1 |
| 3 |
| 6 |
| … |
Dejte tento dotaz do závorek za IN a vnější dotaz najde názvy her:
SELECT nazev
FROM hry
WHERE id IN (SELECT hra_id FROM recenze WHERE hvezdicky = 5)
ORDER BY nazev;| nazev |
|---|
| Cube Logic |
| Dragon Forge |
| Knight's Oath |
| Moon Farm |
| Star Pilots |
| Turbo Karts |
| Zombie Town |
Poddotaz se provede jako první a vrátí seznam: 1, 1, 3, 6, 7, 10, 14, 15. Pak IN u každé hry zkontroluje, jestli je její id v seznamu. Dragon Forge (1) je v seznamu dvakrát, ale na tom nezáleží: IN se ptá jen na to, jestli tam hodnota je, takže každá hra je ve výsledku nejvýš jednou.
Na rozdíl od poddotazů z minulého cvičení smí poddotaz za IN vrátit libovolný počet řádků, klidně i žádný (pak IN nic nenajde). Musí ale vracet právě jeden sloupec, protože IN porovnává jednu hodnotu se seznamem hodnot:
SELECT nazev
FROM hry
WHERE id IN (SELECT hra_id, hvezdicky FROM recenze);Error on line 1: sub-select returns 2 columns - expected 1Zpráva říká, že poddotaz vrací dva sloupce, ale čekal se jeden. Stejné hry byste našli i spojením tabulek:
SELECT h.nazev
FROM hry AS h
JOIN recenze AS r ON r.hra_id = h.id
WHERE r.hvezdicky = 5
ORDER BY h.nazev;| nazev |
|---|
| Cube Logic |
| Dragon Forge |
| Dragon Forge |
| Knight's Oath |
| Moon Farm |
| Star Pilots |
| Turbo Karts |
| Zombie Town |
Spojení vytvoří řádek pro každou odpovídající recenzi, takže Dragon Forge se dvěma pětihvězdičkovými recenzemi je tu dvakrát a potřebovali byste DISTINCT. Co tedy použít? Když ve výsledku potřebujete sloupce druhé tabulky, třeba hvězdičky nebo komentář, potřebujete spojení. Když druhá tabulka jen rozhoduje, které řádky si nechat, IN s poddotazem říká přesně to, co myslíte: „hry, jejichž ID je mezi těmito“.
Typická chyba: = místo IN. WHERE id = (SELECT hra_id FROM recenze WHERE hvezdicky = 5) není v SQLite chyba, ale jak jste viděli v minulém cvičení, vezme jen první hodnotu ze seznamu, takže najde jen Dragon Forge.
Jak psát:
Pokyny
Dotaz v editoru najde hry, které si už někdo koupil, pomocí spojení a DISTINCT. Přepište ho bez spojení: ukažte názvy her, jejichž id je v seznamu hodnot hra_id z tabulky polozky. Použijte IN s poddotazem. Výsledek zůstane stejný:
| nazev |
|---|
| Bakery Story |
| Castle Siege |
| Cube Logic |
| … |
Pod něj ukažte jméno a město zákazníků, kteří zadali objednávku v prosinci, v kterémkoli roce. ID těchto zákazníků najde poddotaz v tabulce objednavky; měsíc z data získáte pomocí strftime('%m', datum). Seřaďte podle jména:
| jmeno | mesto |
|---|---|
| Eva Novotná | Praha |
| Lukáš Procházka | Ostrava |
| Tereza Svobodová | Praha |
| Vojtěch Pokorný | Plzeň |
Poddotaz může obsahovat další poddotaz. Ukažte jméno a e-mail zákazníků, kteří napsali recenzi hry Dragon Forge: poddotaz najde ID autorů recenzí v tabulce recenze a uvnitř něj další poddotaz najde ID hry podle jejího názvu. Seřaďte podle jména:
| jmeno | |
|---|---|
| Anna Kučerová | anna.kucerova@mail.cz |
| Eva Novotná | eva.novotna@mail.cz |
| Jakub Dvořák | jakub.d@mail.cz |
| Matěj Němec | matej.nemec@mail.cz |
Začněte programovat zdarma
2/8