NOT IN a NULL
NOT IN je opak IN: nechá řádky, jejichž hodnota v seznamu není. Tohle jsou hry, které si nikdy nikdo neobjednal:
SELECT nazev
FROM hry
WHERE id NOT IN (SELECT hra_id FROM polozky)
ORDER BY nazev;| nazev |
|---|
| Lost Temple |
| Mystery Manor |
| Robot Rebellion |
Stejný výsledek byste dostali pomocí LEFT JOIN … IS NULL ze 6. lekce, tento dotaz se ale čte skoro jako samotná otázka.
A teď past, do které padají i zkušení programátoři. Kteří zákazníci zatím nikomu obchod nedoporučili? Sloupec doporucil obsahuje ID zákazníka, který obchod doporučil, takže hledáte zákazníky, jejichž id v tomto sloupci není:
SELECT jmeno
FROM zakaznici
WHERE id NOT IN (SELECT doporucil FROM zakaznici)
ORDER BY jmeno;| jmeno |
|---|
Výsledek je prázdný, přestože třeba Filip Beneš obchod zjevně nikomu nedoporučil. Na vině je seznam. Řada zákazníků přišla sama od sebe, takže mají ve sloupci doporucil hodnotu NULL, a poddotaz tak vrací NULL, 1, 1, NULL, 3, 2, NULL a tak dál.
id NOT IN (1, 3, NULL) znamená „id není 1, není 3 a není NULL“. A jak víte ze 3. lekce, porovnání s NULL nikdy neplatí: NULL je neznámá hodnota, a jestli se 12 liší od neznámé hodnoty, je také neznámé. Celá podmínka tak neplatí pro žádného zákazníka:
SELECT 12 NOT IN (1, 3) AS bez_null,
12 NOT IN (1, 3, NULL) AS s_null;| bez_null | s_null |
|---|---|
| 1 | NULL |
1 znamená pravdu. NULL znamená „nevím“ a WHERE nechává jen řádky, pro které podmínka platí. Stačí jedno NULL v seznamu a NOT IN nenajde nic. (IN tento problém nemá: hodnotu, která v seznamu je, najde, ať je v seznamu cokoli dalšího.)
Řešení je nepustit NULL do seznamu: přidejte do poddotazu WHERE doporucil IS NOT NULL. Nebo použijte NOT EXISTS, které se naučíte v dalším cvičení a které tuto past nemá.
Typická chyba: zapomenout na NULL. Kdykoli píšete NOT IN s poddotazem, zeptejte se, jestli může být sloupec poddotazu NULL. Primární klíč jako id nikdy; sloupec jako doporucil ano. A žádnou chybovou zprávu nedostanete: dotaz prostě potichu nic nenajde.
Jak psát:
Pokyny
Dotaz v editoru spadl do pasti a nenajde nic. Opravte ho: nepusťte NULL do seznamu, který vrací poddotaz. Výsledek pak začíná takto:
| jmeno |
|---|
| Anna Kučerová |
| Filip Beneš |
| Kristýna Fialová |
| Lukáš Procházka |
| … |
Pod něj napište dotaz, který ukáže názvy her, které nikdo nehodnotil: jejich id není v seznamu hodnot hra_id z tabulky recenze. Použijte NOT IN s poddotazem. Každá recenze patří k nějaké hře, takže hra_id tam nikdy není NULL a past tu nehrozí. Seřazený podle názvu vypadá výsledek takto:
| nazev |
|---|
| Castle Siege |
| Lost Temple |
| Mystery Manor |
| Robot Rebellion |
Před název každé hry přidejte její žánr a seřaďte hry podle žánru, pak podle názvu:
| zanr | nazev |
|---|---|
| Adventura | Lost Temple |
| Adventura | Mystery Manor |
| Akční | Robot Rebellion |
| Strategie | Castle Siege |
Začněte programovat zdarma
3/8