CASE to SQL-owe if/else
CASE pozwala umieścić logikę warunkową w zapytaniu. Przechodzi po gałęziach WHEN po kolei, wybiera pierwszą pasującą i zwraca wartość po THEN. Jeśli nic nie pasuje, zwraca wartość z ELSE albo NULL, jeśli ELSE nie ma.
Najważniejsze słowo to wyrażenie. CASE daje wartość, więc pasuje wszędzie tam, gdzie dozwolona jest wartość: jako kolumna w SELECT, klucz w ORDER BY, prawa strona porównania, argument funkcji.
Tak wygląda cała konstrukcja: CASE, jedno lub więcej WHEN ... THEN ..., opcjonalne ELSE, a na końcu END. END jest obowiązkowe, a zapominanie o nim to najczęstsza literówka.
Realistyczny przykład
Powiedzmy, że masz tabelę zamówień i chcesz oznaczyć każdy wiersz według wielkości. Zbuduj małą tabelę w miejscu, żeby móc uruchomić zapytanie:
Gałęzie są sprawdzane od góry do dołu. Wygrywa pierwsze dopasowanie, więc ustawiaj je od najbardziej szczegółowej do najbardziej ogólnej. ELSE łapie wszystko, co nie pasowało: bez niego 1200.00 wróciłoby jako NULL, a nie 'large'.
Forma z warunkami a forma prosta
To, co widzisz powyżej, to forma z warunkami (searched CASE): każde WHEN ma własny warunek logiczny. Gdy porównujesz jedno wyrażenie z kilkoma stałymi, jest krótsza forma, czyli forma prosta:
Wyrażenie po CASE jest obliczane raz i porównywane przez = z każdą wartością WHEN. To czytelniejsze, gdy sprawdzasz równość w jednej kolumnie.
Jeden haczyk: prosty CASE używa =, a NULL = NULL w SQL nie jest prawdą. Jeśli status może być NULL, gałęzie 'A'/'B'/'C' go nie złapią i trafisz do ELSE. Aby jawnie obsłużyć NULL, przejdź na formę z warunkami i użyj WHEN status IS NULL THEN ....
CASE w ORDER BY
ORDER BY przyjmuje dowolne wyrażenie, więc CASE sprawdza się tam bez problemu. Przydaje się, gdy chcesz własnej kolejności sortowania, innej niż alfabetyczna czy liczbowa:
Alfabetycznie 'high' < 'low' < 'medium', co jest bezużyteczne przy ustalaniu priorytetów. Zamiana każdego priorytetu na liczbę przez CASE daje kolejność, której naprawdę chcesz. Końcowe , id stabilnie rozstrzyga remisy.
CASE w WHERE
CASE możesz umieścić w WHERE, ale zwykle nie ma takiej potrzeby: łańcuch AND/OR jest czytelniejszy. Błyszczy wtedy, gdy sam warunek zależy od innej wartości:
Produkty w promocji kwalifikują się poniżej 20, zwykłe poniżej 30. Sam próg jest warunkowy. Bez CASE trzeba by napisać (on_sale = 1 AND price < 20) OR (on_sale = 0 AND price < 30): ten sam wynik, więcej szumu.
CASE wewnątrz funkcji agregujących
Tu CASE naprawdę zarabia na siebie. Połącz go z SUM lub COUNT, aby w jednym przejściu policzyć sumy dla podzbioru wierszy. To SQL-owy odpowiednik "policz, ile z nich pasuje":
CASE zwraca 1 dla pasujących wierszy i 0 dla pozostałych, więc SUM staje się liczeniem warunkowym. Ta sama sztuczka działa dla przychodu: zwróć total dla pasujących wierszy i 0 wszędzie indziej. Jeden skan tabeli, kilka warunkowych agregatów.
IIF: skrót dla dwóch gałęzi
Dla jednego warunku z dwoma wynikami SQLite ma IIF(cond, when_true, when_false). To czysty skrót od CASE WHEN cond THEN when_true ELSE when_false END:
Używaj IIF, gdy logika jest binarna i lepiej czyta się w jednej linii. Przejdź na CASE, gdy masz trzy lub więcej gałęzi, musisz osobno obsłużyć NULL albo zależy ci na kolejności sprawdzania kilku klauzul WHEN.
Pułapki, które warto znać
Kilka rzeczy, na których ludzie się potykają:
- Zapomniane
END.CASEotwiera blok, aENDgo zamyka. SQLite zgłosi błąd parsowania dopiero daleko za prawdziwym błędem. - Brak
ELSEoznaczaNULL. Jeśli żadna gałąźWHENnie pasuje, a pominiętoELSE, wynikiem jestNULL. Czasem o to chodzi, ale zwykle nie. - Kolejność gałęzi ma znaczenie. W formie z warunkami wygrywa pierwsze pasujące
WHEN. JeśliWHEN total < 500stoi przedWHEN total < 100, druga gałąź jest nieosiągalna. - Mieszanie typów. Każda gałąź może zwracać inny typ i SQLite nie będzie narzekać, ale dalszy kod może. Staraj się, żeby wszystkie gałęzie zwracały zgodne typy (sam tekst albo same liczby).
- Prosty
CASEiNULL. Jak wspomniano: forma prosta używa=, które nigdy nie pasuje doNULL. Gdy w grę wchodzą NULL, używaj formy z warunkami.
Dalej: funkcje tekstowe
CASE pozwala rozgałęziać logikę na podstawie wartości, a następny rozdział zaczyna się od przekształcania wartości. Funkcje tekstowe (UPPER, LOWER, SUBSTR, REPLACE, wzorce LIKE) wykonują codzienną pracę czyszczenia i przeformatowywania kolumn tekstowych. To temat następnej strony.
Najczęściej zadawane pytania
Czym jest wyrażenie CASE w SQLite?
Wyrażenie CASE to SQL-owa wersja if/else: sprawdza warunki i zwraca wartość. To wyrażenie, a nie instrukcja, więc możesz go użyć wszędzie tam, gdzie dozwolona jest wartość: w SELECT, WHERE, ORDER BY, UPDATE, a nawet wewnątrz funkcji agregujących. Każda gałąź ma postać WHEN condition THEN value, a na końcu może pojawić się opcjonalne ELSE.
Czym różni się prosty CASE od CASE z warunkami w SQLite?
Prosty CASE porównuje jedno wyrażenie z kilkoma wartościami: CASE status WHEN 'A' THEN ... WHEN 'B' THEN ... END. CASE z warunkami sprawdza osobny warunek logiczny w każdej gałęzi: CASE WHEN price > 100 THEN ... WHEN qty = 0 THEN ... END. Forma z warunkami jest bardziej elastyczna: może swobodnie łączyć kolumny, operatory i sprawdzanie NULL.
Kiedy używać IIF zamiast CASE w SQLite?
IIF(cond, a, b) to skrót od CASE WHEN cond THEN a ELSE b END. Używaj IIF przy logice z dwiema gałęziami, gdy czyta się ją łatwiej. Po CASE sięgaj, gdy masz trzy lub więcej gałęzi, zależy ci na kolejności sprawdzania albo musisz jawnie obsłużyć NULL przez WHEN col IS NULL.