В 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