В SQL, CASE оператор оценява списък с условия и връща един от множеството възможни изрази за резултат.
В някои отношения SQL CASE изявлението е нещо подобно на IF...ELSE изявление в това, че ни позволява да проверим за дадено условие и да върнем различен резултат в зависимост от резултата.
Това CASE ли е Изявление или CASE Израз?
В SQL понякога нещата се наричат „изявление“, когато всъщност са нещо друго. SQL „CASE твърдение“ е примерен случай (съжалявам за каламбура!).
CASE изразът се нарича в стандарта SQL (ISO/IEC 9075) като CASE израз . Целта му е „да посочи условна стойност“.
Въпреки това, някои СУБД правят разлика между CASE оператор и CASE израз и имат малко по-различен синтаксис за всеки. Например и MySQL, и MariaDB предоставят CASE оператор и CASE оператор като две отделни характеристики, всяка с малко различен синтаксис.
CASE Формати
В SQL има два формата на CASE израз:
- Прост
CASEизраз - Търсене
CASEизраз
По-долу са дадени примери за всеки.
Простият CASE Израз
Простият CASE израз сравнява израз с набор от прости изрази, за да определи резултата.
Пример:
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; Резултат:
Grass
Този пример е направен в MySQL, но действителният CASE изразът трябва да работи в повечето основни RDBMS.
В този пример моят CASE изразът е част от SELECT изявление. Той проверява за три условия и има ELSE за да се погрижат за всичко, което не е обхванато от трите условия.
В този случай животното Cow съвпада с третия WHEN израз и изразът, предоставен от неговия THEN се връща.
За да бъде ясно, действителният CASE изразът е тази част:
CASE @animal
WHEN 'Bird' THEN 'Seed'
WHEN 'Dog' THEN 'Beef'
WHEN 'Cow' THEN 'Grass'
ELSE 'Leftovers'
END
Какъв CASE прави, е да провери стойността на всеки WHEN израз спрямо входния израз. В този пример @animal променливата е входният израз. Следователно, той проверява стойността на всеки WHEN израз срещу @animal променлива.
Когато/ако намери съвпадение, той връща израза, предоставен от съответния THEN .
Моят пример използва три WHEN изрази, но можех да използвам повече и можех да използвам по-малко, в зависимост от изискванията.
Търсеният CASE Израз
Търсеният CASE Expression оценява набор от булеви изрази, за да определи резултата.
Ето пример за търсен CASE израз.
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; Резултат:
Well done!
Търсеният CASE изразът няма входен израз като простия CASE израз.
Ще си спомните това в нашия прост CASE израз, той започна с CASE @animal , и следователно знаехме, че WHEN всички изрази се оценяваха спрямо стойността на @animal .
С търсения CASE израз, ние не предоставяме входен израз в началото по този начин. Вместо това всеки WHEN изразът включва булев израз, за който да се оценява.
Пример за база данни
Ето пример, който демонстрира как CASE изразът може да се използва в рамките на заявка за база данни.
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; Резултат:
+---------------+------------+------------+ | 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 | +---------------+------------+------------+
Този пример използва търсен CASE израз за оценка на резултатите от Population колона на City маса.
ELSE е по избор
ELSE аргументът е по избор. Ако пропуснем ELSE и нито едно от условията не се задейства, резултатът е NULL .
Ето какво се случва, когато пропуснем ELSE клауза от предишния пример:
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; Резултат:
+---------------+------------+-----------+ | 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 в UPDATE Изявление
Нека добавим колона към City таблица от предишния пример:
ALTER TABLE City
ADD COLUMN Size VARCHAR(30) AFTER Population;
SELECT * FROM City
LIMIT 10; Ето как изглежда сега:
+----+----------------+-------------+---------------+------------+------+ | 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 | +----+----------------+-------------+---------------+------------+------+
Не сме вмъкнали никакви данни в новия Size колона, така че връща NULL във всеки ред.
Вече можем да използваме CASE израз за актуализиране на Size колона със стойност, която зависи от стойността в Population колона:
UPDATE City
SET Size =
CASE
WHEN Population > 2000000 THEN 'Huge City'
WHEN Population >= 1000000 AND Population < 2000000 THEN 'Big City'
ELSE 'Small City'
END; Сега нека изберем данни от таблицата:
SELECT * FROM City
WHERE CountryCode = 'USA'
ORDER BY Population DESC
LIMIT 20; Резултат:
+------+---------------+-------------+---------------+------------+------------+ | 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 в INSERT Изявление
Да предположим, че имаме следната таблица в база данни на SQL Server:
+---------+-----------+-----------+--------------+ | DogId | DogName | GoodDog | Dinner | |---------+-----------+-----------+--------------| | 1001 | Brian | 1 | Sunday Roast | | 1002 | Rambo | 0 | Airline food | | 1003 | BamBam | 1 | Sunday Roast | +---------+-----------+-----------+--------------+
Нека вмъкнем нов ред в тази таблица. Но нека използваме CASE израз, за да вмъкнете подходящата стойност в Dinner колона, в зависимост от стойността в GoodDog колона:
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
);
Тук CASE Expression оценява стойността на променлива, която току-що сме задали, и след това вмъква подходящата стойност в Dinner колона.
Сега нека отново проверим таблицата:
SELECT * FROM Dogs; Резултат:
+---------+-----------+-----------+--------------+ | DogId | DogName | GoodDog | Dinner | |---------+-----------+-----------+--------------| | 1001 | Brian | 1 | Sunday Roast | | 1002 | Rambo | 0 | Airline food | | 1003 | BamBam | 1 | Sunday Roast | | 1004 | Lazy | 0 | Airline food | +---------+-----------+-----------+--------------+
Можем да видим, че подходящата стойност е в Dinner колона.
CASE в ORDER BY Клауза
CASE изразът може да се използва във всеки израз или клауза, която позволява валиден израз. Следователно можете да го използвате в изрази като SELECT , UPDATE , DELETE и SET и в клаузи като IN , WHERE , ORDER BY , GROUP BY и HAVING .
Използване на CASE израз в ORDER BY на изявление клаузата може да бъде удобна, когато искате да направите специално изключение за определени стойности, когато поръчвате резултатите си.
Да предположим, че изпълняваме следната заявка срещу таблица, съдържаща музикални жанрове.
SELECT Genre
FROM Genres
ORDER BY Genre ASC; Резултат:
+---------+ | Genre | +---------+ | Blues | | Country | | Hip Hop | | Jazz | | Other | | Pop | | Punk | | Rap | | Rock | +---------+
Тук подреждаме резултатите по Genre колона във възходящ ред.
Това е добре с изключение на едно нещо. Жанрът, наречен Other . Не би ли било хубаво, ако можем да преместим Other до дъното?
Можем да постигнем това с CASE израз, като вземете горната заявка и я модифицирате, както следва.
SELECT Genre
FROM Genres
ORDER BY
CASE Genre
WHEN 'Other' THEN 1
ELSE 0
END
ASC, Genre ASC; Резултат:
+---------+ | Genre | +---------+ | Blues | | Country | | Hip Hop | | Jazz | | Pop | | Punk | | Rap | | Rock | | Other | +---------+
COALESCE() и NULLIF() Функции
В зависимост от сценария можем да използваме функции като COALESCE() и NULLIF() като пряк път, вместо да използвате CASE израз.
Тези две функции са стандарт на SQL и работят както следва:
NULLIF (V1, V2) Еквивалентен на:
CASE WHEN V1=V2 THEN NULL ELSE V1 END И:
COALESCE (V1, V2) Еквивалентен на:
CASE WHEN V1 IS NOT NULL THEN V1 ELSE V2 END Също така:
COALESCE (V1, V2, ..., Vn) Еквивалентен на:
CASE WHEN V1 IS NOT NULL THEN V1 ELSE COALESCE (V2, ..., Vn) END