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
CASEwyrażenie - Przeszukano
CASEwyraż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