Niedawno odkryłem dość irytujący problem w MySQL. Otóż okazuje się, że nie można sumować wartości NULL z dowolną cyfrą. Wynik takiego zapytania:
SELECT NULL + 5 AS foo;
Zwróci nam wartość NULL. Jak na mój chłopski rozum to powinna być wartość 5. Ten mały problem, może czasami całkiem sprawnie pokrzyżować jakieś zliczania/etc przez co wyniki, które otrzymamy mogą mijać się z rzeczywistością.
Na szczęście udało mi się znaleźć całkiem zgrabne rozwiązanie. Jest nim funkcja COALESCE, która zwraca pierwszą nie-pustą wartość podaną podczas wywołania. Drobna modyfikacja zapytania i mamy poprawny wynik:
SELECT COALESCE(NULL, 0) + 5 AS foo;
7 Komentarze
Zasadniczo to MySQL ma rację – powinno być NULL. NULL gdyby miało wartość 0 byłoby zerem, nie null’em.
NULL oznacza wartość nieokreśloną, nieznaną. Równanie x + 5 = y – mniej więcej tak to nalezy rozumieć.
Wykorzystanie CASE nie byłoby efektywniejsze?
W sumie to masz rację.
Co do Case, to wydaje mi się to takim przerostem formy nad treścią :) ew skorzystałbym z IFNULL
Użytkownikowi nie wyświetlimy “Liczba Twoich punktów: NULL” a o to nie trudno. Ładniej obsłużyć to na poziomie wyciągania danych :) A sama konstrukcja jest ładniejsza niż IF i CASE w mysql. Niestety nie wiem jak z wydajnością? Macie jakieś doświadczenia?
Tak jak poprzednik, mimo wszystko polecam użyć PHP do zliczania danych. Mysql powinien je tylko wyciągać. A w PHP przecież zawsze można zrobić sobie rzutowanie na (integer) i z NULLa mieć `0`.
to znane zagdanienie relacyjnych baz danych. null to wartosc nieznana ale to nie zero!!! baza danych nie wie co z tym zrobic wiec nie moze dac wyniku jakiegokolwiek dzialania. najprostszym i jednym z najbardziej zalecanych rozwiazan jest unikanie wartosci null poprzez klauzule not null przy definicji kolumny. dlaczego? poniewaz wielu specjalistow uwaza to za jeden z najwiekszych problemow relacyjnych baz danych i jezyka sql ze NULL nie oznacza konkretnego stanu a skoro nie oznacza takowego to lepiej nie dopuscic do wystepowania wartosci null.
polecam ksiazki Joe Celko ktore zajmuja sie tym i wieloma innymi zaawansowanymi tematami jezyka sql.
Rafał Piekarski -> Użycie PHP do zliczania danych nie zawsze jest możliwe, jeśli SQL ma posortować wynik zapytania według jakiegoś działania na kilku polach i nie zwraca całej tablicy, tylko wybrany fragment (jest użyty LIMIT). Ja mam właśnie taki przypadek i sumowane pola mogą mieć NULL (musiałem użyć NULL, bo potrzebne mi rozróżnienie na: brak wartości, 0 i >0). Rezygnacja z NULL nie wchodzi więc w grę i wybrałem rozwiązanie z COALESCE.
A najlepiej już na poziomie projektowania bazy nie dopuścić do wartości NULL. Lepiej ustawić NOT NULL i wartość domyślną, np. 0. Koniec końców – COALESCE jest wydajniejsze niż CASE.
A NULLa możesz sobie wyobrazić jako czarną dziurę. Nieważne ile tam wrzucisz i tak nie zapełnisz. Zawsze w wyniku będzie NULL. Czy to COUNT, czy SUM, czy konkatenacja, czy działania boolowskie, czy jakiekolwiek inne działanie z wartością nieokreśloną.