Nechápu SQL, nebo SQL nechápe mě? rubrika: Databáze: SQL

9 Vašek Ch.
položil/-a 1.2.2014

Reálný dotaz nad MySQL 5.1 (InnoDB), a nechápu, co se to to děje.
Máme tabulku stock_lists reprezentující naskladnění a tabulku stock_list_items reprezentující položky naskladnění. Položka naskladnění se váže k produktu a byla objednávana v počtu ordered_amount. Tenhle dotaz funguje a má vrátit id produktu v jednom sloupci a celkové objednané nenaskladněné (sl.stocked_at IS NULL) množství ve sloupci druhém.

SELECT p.id, SUM(sli.ordered_amount) amount
FROM products p
JOIN stock_list_items sli ON sli.product_id = p.id
JOIN stock_lists sl ON sl.id = sli.stock_list_id
WHERE
    sl.stocked_at IS NULL
    AND p.id IN (1, 2, 3)
GROUP BY p.id

Problém: Potřebujeme spočítat množství jen pro stock listy, které nemají state cancelled. Logicky jsme tedy přidali podmínku ...AND NOT sl.state ='cancelled' a ouha... Vypadly mi nejen položky se stavem cancelled, ale i všechny ostatní položky, které měly tenhle sloupec na NULL. Vyřešilo to ...AND (sl.state IS NULL OR NOT sl.state = 'cancelled').
Tuhle chybu udělal kolega, ale pravděpodobně bych ji udělal taky. O co se jedná? Proč ty se stavem NULL vypadnou taky?

Komentáře

  • dzejkob : http://dev.mysql.com/doc/refman/5.0/en/working-with-null.html 1.2.2014
  • dzejkob : tedy operace s NULL jsou NULL a NOT NULL je zase NULL 1.2.2014
  • Vašek Ch. : Hmm, je to strašně neintuitivní a v tomhle případě zrádné, ale asi to má svoji logiku. Díky! 1.2.2014
  • pavel.stehule : Co je na tom neintuitivní - NULL není 0 - není to jenom nějaká konstanta, která není porovnatelná s libovolnou jinou konstantou, ale i signál, že něco nevím a tudíž na tom nemůžu jednoduše spočítat výsledek. Normálně to nevadí - při rozumně navrženém schématu a procesech. Předpokládám, že určitě nikdo v normálním skladu nechce mít důležitá data o stavu naskladněných položek NULL. 1.2.2014
  • gilhad : NULL znamená "nebylo zadáno a tak nevím" (což je o dost jiné, než "bylo zadáno jakožto nula"). Důsledkem toho pokud je sl.state NULL (nevím) je odpověď na otázku "sl.state = 'cancelled'" opět "nevím" čili NULL, stejně jako odpověď na otázku "NOT sl.state = 'cancelled'" je opět "nevím" čili NULL. Pokud jste hodnotu sl.state nezadal, tak může být jakákoli a engine ji logicky buď musí odmítnout zpracovávat (a dát chybu něco jako "nezadaná hodnota"), nebo výsledkem jakéhokoli porovnávání musí být "hodnota není známa", což je v případě SQL právě NULL 2.2.2014

Pro plný přístup na Devel.cz se prosím přihlaste:

Rychlé přihlášení přes sociální sítě:

Nebo se přihlaste jménem a heslem:

Zadejte prosím svou e-mailovou adresu.
Zadejte své heslo.