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_nulls_null
1NULL

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.

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:

zanrnazev
AdventuraLost Temple
AdventuraMystery Manor
AkčníRobot Rebellion
StrategieCastle Siege

Začněte programovat zdarma

Registrací souhlasíte s provozními podmínkami a zásadami ochrany osobních údajů.

Nebo se registrujte pomocí:

3/8