W SQL CASE
instrukcja ocenia listę warunków i zwraca jedno z wielu możliwych wyrażeń wynikowych.
W pewnym sensie SQL CASE
Instrukcja jest podobna do IF...ELSE
stwierdzenie, że pozwala nam sprawdzić dany warunek i zwrócić inny wynik w zależności od wyniku.
Czy to CASE
? Oświadczenie lub CASE
Wyrażenie?
W SQL czasami rzeczy są określane jako „oświadczenie”, podczas gdy w rzeczywistości są czymś innym. SQL „CASE
oświadczenie” jest tego przykładem (przepraszam za kalambur!).
CASE
instrukcja jest określana w standardzie SQL (ISO/IEC 9075) jako CASE
wyrażenie . Jego celem jest „określenie wartości warunkowej”.
Jednak niektóre DBMS rozróżniają CASE
oświadczenie i CASE
wyrażenie i mają nieco inną składnię dla każdego. Na przykład zarówno MySQL, jak i MariaDB zapewniają CASE
oświadczenie i CASE
operator jako dwie różne cechy, każda z nieco inną składnią.
CASE
Formaty
W SQL istnieją dwa formaty CASE
wyrażenie:
- Prosty
CASE
wyrażenie - Przeszukano
CASE
wyrażenie
Poniżej znajdują się przykłady każdego z nich.
Prosty CASE
Wyrażenie
Prosty CASE
wyrażenie porównuje wyrażenie z zestawem prostych wyrażeń w celu określenia wyniku.
Przykład:
DECLARE @animal VARCHAR(40);
SET @animal = 'Cow';
SELECT
CASE @animal
WHEN 'Bird' THEN 'Seed'
WHEN 'Dog' THEN 'Beef'
WHEN 'Cow' THEN 'Grass'
ELSE 'Leftovers'
END;
Wynik:
Grass
Ten przykład został wykonany w MySQL, ale rzeczywisty CASE
wyrażenie powinno działać w większości głównych systemów RDBMS.
W tym przykładzie mój CASE
wyrażenie jest częścią SELECT
oświadczenie. Sprawdza trzy warunki i ma ELSE
aby zaspokoić wszystko, co nie jest objęte tymi trzema warunkami.
W tym przypadku zwierzę Cow
pasuje do trzeciego WHEN
wyrażenie i wyrażenie dostarczone przez jego THEN
jest zwracany.
Żeby było jasne, rzeczywisty CASE
wyrażenie to ta część:
CASE @animal
WHEN 'Bird' THEN 'Seed'
WHEN 'Dog' THEN 'Beef'
WHEN 'Cow' THEN 'Grass'
ELSE 'Leftovers'
END
Jaki CASE
sprawdza wartość każdego WHEN
wyrażenie w stosunku do wyrażenia wejściowego. W tym przykładzie @animal
zmienna jest wyrażeniem wejściowym. Dlatego sprawdza wartość każdego WHEN
wyrażenie przeciwko @animal
zmienna.
Kiedy/jeśli znajdzie dopasowanie, zwraca wyrażenie dostarczone przez odpowiedni THEN
.
Mój przykład używa trzech WHEN
wyrażeń, ale mogłem użyć więcej i mogłem użyć mniej, w zależności od wymagań.
Przeszukiwany CASE
Wyrażenie
Wyszukiwany CASE
wyrażenie oblicza zestaw wyrażeń logicznych w celu określenia wyniku.
Oto przykład przeszukiwanego CASE
wyrażenie.
DECLARE @score int;
SET @score = 7;
SELECT
CASE
WHEN @score > 8 THEN 'Congratulations!'
WHEN @score > 5 AND @score < 8 THEN 'Well done!'
ELSE 'Try harder next time'
END;
Wynik:
Well done!
Wyszukiwany CASE
wyrażenie nie ma wyrażenia wejściowego, takiego jak prosty CASE
wyrażenie.
Przypomnisz to sobie w naszym prostym CASE
wyrażenie, zaczęło się od CASE
@animal
, dlatego wiedzieliśmy, że WHEN
wszystkie wyrażenia były oceniane względem wartości @animal
.
Z wyszukiwanym CASE
wyrażenie, nie zapewniamy wyrażenia wejściowego na początku w ten sposób. Zamiast tego każde WHEN
wyrażenie zawiera wyrażenie logiczne, dla którego ma być oceniane.
Przykład bazy danych
Oto przykład, który pokazuje, jak CASE
wyrażenie może być użyte w zapytaniu do bazy danych.
USE World;
SELECT
Name,
Population,
CASE
WHEN Population > 2000000 THEN 'Huge City'
WHEN Population >= 1000000 AND Population < 2000000 THEN 'Big City'
ELSE 'Small City'
END AS Size
FROM City
WHERE CountryCode = 'USA'
ORDER BY Population DESC
LIMIT 20;
Wynik:
+---------------+------------+------------+ | Name | Population | Size | +---------------+------------+------------+ | New York | 8008278 | Huge City | | Los Angeles | 3694820 | Huge City | | Chicago | 2896016 | Huge City | | Houston | 1953631 | Big City | | Philadelphia | 1517550 | Big City | | Phoenix | 1321045 | Big City | | San Diego | 1223400 | Big City | | Dallas | 1188580 | Big City | | San Antonio | 1144646 | Big City | | Detroit | 951270 | Small City | | San Jose | 894943 | Small City | | Indianapolis | 791926 | Small City | | San Francisco | 776733 | Small City | | Jacksonville | 735167 | Small City | | Columbus | 711470 | Small City | | Austin | 656562 | Small City | | Baltimore | 651154 | Small City | | Memphis | 650100 | Small City | | Milwaukee | 596974 | Small City | | Boston | 589141 | Small City | +---------------+------------+------------+
W tym przykładzie użyto przeszukiwanego CASE
wyrażenie do oceny wyników z Population
kolumna City
stół.
ELSE
jest opcjonalne
ELSE
argument jest opcjonalny. Jeśli pominiemy ELSE
, a żaden z warunków nie jest wyzwalany, wynikiem jest NULL
.
Oto, co się dzieje, gdy pominiemy ELSE
klauzula z poprzedniego przykładu:
USE World;
SELECT
Name,
Population,
CASE
WHEN Population > 2000000 THEN 'Huge City'
WHEN Population >= 1000000 AND Population < 2000000 THEN 'Big City'
END AS Size
FROM City
WHERE CountryCode = 'USA'
ORDER BY Population DESC
LIMIT 20;
Wynik:
+---------------+------------+-----------+ | Name | Population | Size | +---------------+------------+-----------+ | New York | 8008278 | Huge City | | Los Angeles | 3694820 | Huge City | | Chicago | 2896016 | Huge City | | Houston | 1953631 | Big City | | Philadelphia | 1517550 | Big City | | Phoenix | 1321045 | Big City | | San Diego | 1223400 | Big City | | Dallas | 1188580 | Big City | | San Antonio | 1144646 | Big City | | Detroit | 951270 | NULL | | San Jose | 894943 | NULL | | Indianapolis | 791926 | NULL | | San Francisco | 776733 | NULL | | Jacksonville | 735167 | NULL | | Columbus | 711470 | NULL | | Austin | 656562 | NULL | | Baltimore | 651154 | NULL | | Memphis | 650100 | NULL | | Milwaukee | 596974 | NULL | | Boston | 589141 | NULL | +---------------+------------+-----------+
CASE
w UPDATE
Oświadczenie
Dodajmy kolumnę do City
tabela z poprzedniego przykładu:
ALTER TABLE City
ADD COLUMN Size VARCHAR(30) AFTER Population;
SELECT * FROM City
LIMIT 10;
Oto jak teraz wygląda:
+----+----------------+-------------+---------------+------------+------+ | ID | Name | CountryCode | District | Population | Size | +----+----------------+-------------+---------------+------------+------+ | 1 | Kabul | AFG | Kabol | 1780000 | NULL | | 2 | Qandahar | AFG | Qandahar | 237500 | NULL | | 3 | Herat | AFG | Herat | 186800 | NULL | | 4 | Mazar-e-Sharif | AFG | Balkh | 127800 | NULL | | 5 | Amsterdam | NLD | Noord-Holland | 731200 | NULL | | 6 | Rotterdam | NLD | Zuid-Holland | 593321 | NULL | | 7 | Haag | NLD | Zuid-Holland | 440900 | NULL | | 8 | Utrecht | NLD | Utrecht | 234323 | NULL | | 9 | Eindhoven | NLD | Noord-Brabant | 201843 | NULL | | 10 | Tilburg | NLD | Noord-Brabant | 193238 | NULL | +----+----------------+-------------+---------------+------------+------+
Nie wstawiliśmy żadnych danych do nowego Size
kolumna, więc zwraca NULL
w każdym rzędzie.
Możemy teraz użyć CASE
wyrażenie do aktualizacji Size
kolumna z wartością zależną od wartości w Population
kolumna:
UPDATE City
SET Size =
CASE
WHEN Population > 2000000 THEN 'Huge City'
WHEN Population >= 1000000 AND Population < 2000000 THEN 'Big City'
ELSE 'Small City'
END;
Teraz wybierzmy dane z tabeli:
SELECT * FROM City
WHERE CountryCode = 'USA'
ORDER BY Population DESC
LIMIT 20;
Wynik:
+------+---------------+-------------+---------------+------------+------------+ | ID | Name | CountryCode | District | Population | Size | +------+---------------+-------------+---------------+------------+------------+ | 3793 | New York | USA | New York | 8008278 | Huge City | | 3794 | Los Angeles | USA | California | 3694820 | Huge City | | 3795 | Chicago | USA | Illinois | 2896016 | Huge City | | 3796 | Houston | USA | Texas | 1953631 | Big City | | 3797 | Philadelphia | USA | Pennsylvania | 1517550 | Big City | | 3798 | Phoenix | USA | Arizona | 1321045 | Big City | | 3799 | San Diego | USA | California | 1223400 | Big City | | 3800 | Dallas | USA | Texas | 1188580 | Big City | | 3801 | San Antonio | USA | Texas | 1144646 | Big City | | 3802 | Detroit | USA | Michigan | 951270 | Small City | | 3803 | San Jose | USA | California | 894943 | Small City | | 3804 | Indianapolis | USA | Indiana | 791926 | Small City | | 3805 | San Francisco | USA | California | 776733 | Small City | | 3806 | Jacksonville | USA | Florida | 735167 | Small City | | 3807 | Columbus | USA | Ohio | 711470 | Small City | | 3808 | Austin | USA | Texas | 656562 | Small City | | 3809 | Baltimore | USA | Maryland | 651154 | Small City | | 3810 | Memphis | USA | Tennessee | 650100 | Small City | | 3811 | Milwaukee | USA | Wisconsin | 596974 | Small City | | 3812 | Boston | USA | Massachusetts | 589141 | Small City | +------+---------------+-------------+---------------+------------+------------+
CASE
w INSERT
Oświadczenie
Załóżmy, że mamy następującą tabelę w bazie danych SQL Server:
+---------+-----------+-----------+--------------+ | DogId | DogName | GoodDog | Dinner | |---------+-----------+-----------+--------------| | 1001 | Brian | 1 | Sunday Roast | | 1002 | Rambo | 0 | Airline food | | 1003 | BamBam | 1 | Sunday Roast | +---------+-----------+-----------+--------------+
Wstawmy nowy wiersz do tej tabeli. Ale użyjmy CASE
wyrażenie do wstawienia odpowiedniej wartości do Dinner
kolumna, w zależności od wartości w GoodDog
kolumna:
DECLARE @DogName nvarchar(60), @GoodDog bit;
SET @DogName = 'Lazy';
SET @GoodDog = 0;
INSERT INTO Dogs ( DogName, GoodDog, Dinner )
VALUES (
@DogName,
@GoodDog,
CASE @GoodDog
WHEN 1 THEN 'Sunday Roast'
ELSE 'Airline food'
END
);
Tutaj CASE
wyrażenie oceniło wartość zmiennej, którą właśnie ustawiliśmy, a następnie wstawił odpowiednią wartość do Dinner
kolumna.
Teraz sprawdźmy ponownie tabelę:
SELECT * FROM Dogs;
Wynik:
+---------+-----------+-----------+--------------+ | DogId | DogName | GoodDog | Dinner | |---------+-----------+-----------+--------------| | 1001 | Brian | 1 | Sunday Roast | | 1002 | Rambo | 0 | Airline food | | 1003 | BamBam | 1 | Sunday Roast | | 1004 | Lazy | 0 | Airline food | +---------+-----------+-----------+--------------+
Widzimy, że odpowiednia wartość znajduje się w Dinner
kolumna.
CASE
w ORDER BY
Klauzula
CASE
wyrażenie może być użyte w dowolnej instrukcji lub klauzuli, która zezwala na prawidłowe wyrażenie. Dlatego możesz go używać w instrukcjach takich jak SELECT
, UPDATE
, DELETE
i SET
oraz w klauzulach, takich jak IN
, WHERE
, ORDER BY
, GROUP BY
i HAVING
.
Korzystanie z CASE
wyrażenie w ORDER BY
instrukcji Klauzula może być przydatna, gdy chcesz zrobić specjalny wyjątek dla pewnych wartości podczas porządkowania wyników.
Załóżmy, że uruchamiamy następujące zapytanie w tabeli zawierającej gatunki muzyczne.
SELECT Genre
FROM Genres
ORDER BY Genre ASC;
Wynik:
+---------+ | Genre | +---------+ | Blues | | Country | | Hip Hop | | Jazz | | Other | | Pop | | Punk | | Rap | | Rock | +---------+
Tutaj sortujemy wyniki według Genre
kolumna w porządku rosnącym.
To jest w porządku, z wyjątkiem jednej rzeczy. Gatunek o nazwie Other
. Czy nie byłoby miło, gdybyśmy mogli przenieść Other
? na sam dół?
Możemy to osiągnąć za pomocą CASE
wyrażenie, biorąc powyższe zapytanie i modyfikując je w następujący sposób.
SELECT Genre
FROM Genres
ORDER BY
CASE Genre
WHEN 'Other' THEN 1
ELSE 0
END
ASC, Genre ASC;
Wynik:
+---------+ | Genre | +---------+ | Blues | | Country | | Hip Hop | | Jazz | | Pop | | Punk | | Rap | | Rock | | Other | +---------+
COALESCE()
i NULLIF()
Funkcje
W zależności od scenariusza możemy użyć funkcji takich jak COALESCE()
i NULLIF()
jako skrót, zamiast używania CASE
wyrażenie.
Te dwie funkcje są standardem SQL i działają w następujący sposób:
NULLIF (V1, V2)
Jest odpowiednikiem:
CASE WHEN V1=V2 THEN NULL ELSE V1 END
Oraz:
COALESCE (V1, V2)
Jest odpowiednikiem:
CASE WHEN V1 IS NOT NULL THEN V1 ELSE V2 END
Również:
COALESCE (V1, V2, ..., Vn)
Jest odpowiednikiem:
CASE WHEN V1 IS NOT NULL THEN V1 ELSE COALESCE (V2, ..., Vn) END