I SQL, CASE
satsen utvärderar en lista med villkor och returnerar ett av flera möjliga resultatuttryck.
På vissa sätt, SQL CASE
uttalandet är ungefär likt IF...ELSE
påstående genom att det tillåter oss att kontrollera ett givet tillstånd och returnera ett annat resultat beroende på resultatet.
Är det ett CASE
Uttalande eller CASE
Uttryck?
I SQL hänvisas ibland saker till som ett "påstående" när de i själva verket är något annat. SQL-koden "CASE
statement” är ett exempel (förlåt om ordleken!).
CASE
satsen hänvisas till i SQL-standarden (ISO/IEC 9075) som CASE
uttryck . Dess syfte är att "specificera ett villkorligt värde".
Vissa DBMS skiljer dock mellan CASE
satsen och CASE
uttryck och har en något olika syntax för varje. Till exempel tillhandahåller både MySQL och MariaDB CASE
satsen och CASE
operatorn som två distinkta funktioner, var och en med något olika syntax.
CASE
Format
I SQL finns det två format av CASE
uttryck:
- Enkelt
CASE
uttryck - Sökte i
CASE
uttryck
Nedan finns exempel på var och en.
Det enkla CASE
Uttryck
Det enkla CASE
expression jämför ett uttryck med en uppsättning enkla uttryck för att bestämma resultatet.
Exempel:
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;
Resultat:
Grass
Detta exempel gjordes i MySQL, men det faktiska CASE
uttryck bör fungera över de flesta stora RDBMS.
I det här exemplet, mitt CASE
uttryck är en del av en SELECT
påstående. Den söker efter tre villkor och har en ELSE
för att tillgodose allt som inte omfattas av de tre villkoren.
I det här fallet, djuret Cow
matchar den tredje WHEN
uttryck och uttrycket som tillhandahålls av dess THEN
returneras.
För att vara tydlig, det faktiska CASE
uttryck är denna del:
CASE @animal
WHEN 'Bird' THEN 'Seed'
WHEN 'Dog' THEN 'Beef'
WHEN 'Cow' THEN 'Grass'
ELSE 'Leftovers'
END
Vad CASE
är att kontrollera värdet för varje WHEN
uttryck mot inmatningsuttrycket. I det här exemplet, @animal
variabel är inmatningsuttrycket. Därför kontrollerar den värdet för varje WHEN
uttryck mot @animal
variabel.
När/om den hittar en matchning returnerar den uttrycket som tillhandahålls av motsvarande THEN
.
Mitt exempel använder tre WHEN
uttryck, men jag kunde ha använt mer och jag kunde ha använt mindre, beroende på kraven.
Det sökta CASE
Uttryck
Det sökta CASE
expression utvärderar en uppsättning booleska uttryck för att bestämma resultatet.
Här är ett exempel på ett sökt CASE
uttryck.
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;
Resultat:
Well done!
Det sökta CASE
uttryck har inte ett inmatningsuttryck som det enkla CASE
uttryck.
Du kommer ihåg det i vårt enkla CASE
uttryck började det med CASE
@animal
, och därför visste vi att WHEN
alla uttryck utvärderades mot värdet av @animal
.
Med den sökta CASE
uttryck, vi tillhandahåller inte ett inmatningsuttryck i början på det sättet. Istället, varje WHEN
uttryck inkluderar ett booleskt uttryck som det ska utvärderas mot.
Ett databasexempel
Här är ett exempel som visar hur CASE
uttryck kan användas i en databasfråga.
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;
Resultat:
+---------------+------------+------------+ | 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 | +---------------+------------+------------+
Det här exemplet använder ett sökt CASE
uttryck för att utvärdera resultaten från Population
kolumnen i City
tabell.
ELSE
är valfritt
ELSE
argument är valfritt. Om vi utelämnar ELSE
, och inget av villkoren utlöses, blir resultatet NULL
.
Det här är vad som händer när vi utelämnar ELSE
klausul från föregående exempel:
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;
Resultat:
+---------------+------------+-----------+ | 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
i en UPDATE
Uttalande
Låt oss lägga till en kolumn i City
tabell från föregående exempel:
ALTER TABLE City
ADD COLUMN Size VARCHAR(30) AFTER Population;
SELECT * FROM City
LIMIT 10;
Så här ser det ut nu:
+----+----------------+-------------+---------------+------------+------+ | 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 | +----+----------------+-------------+---------------+------------+------+
Vi har inte infogat några data i den nya Size
kolumn, så den returnerar NULL
på varje rad.
Vi kan nu använda en CASE
uttryck för att uppdatera Size
kolumn med ett värde som beror på värdet i Population
kolumn:
UPDATE City
SET Size =
CASE
WHEN Population > 2000000 THEN 'Huge City'
WHEN Population >= 1000000 AND Population < 2000000 THEN 'Big City'
ELSE 'Small City'
END;
Låt oss nu välja data från tabellen:
SELECT * FROM City
WHERE CountryCode = 'USA'
ORDER BY Population DESC
LIMIT 20;
Resultat:
+------+---------------+-------------+---------------+------------+------------+ | 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
i en INSERT
Uttalande
Anta att vi har följande tabell i en SQL Server-databas:
+---------+-----------+-----------+--------------+ | DogId | DogName | GoodDog | Dinner | |---------+-----------+-----------+--------------| | 1001 | Brian | 1 | Sunday Roast | | 1002 | Rambo | 0 | Airline food | | 1003 | BamBam | 1 | Sunday Roast | +---------+-----------+-----------+--------------+
Låt oss infoga en ny rad i den tabellen. Men låt oss använda CASE
uttryck för att infoga lämpligt värde i Dinner
kolumnen, beroende på värdet i GoodDog
kolumn:
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
);
Här, CASE
expression utvärderade värdet på en variabel som vi precis hade ställt in och infogade sedan lämpligt värde i Dinner
kolumn.
Låt oss nu kolla tabellen igen:
SELECT * FROM Dogs;
Resultat:
+---------+-----------+-----------+--------------+ | DogId | DogName | GoodDog | Dinner | |---------+-----------+-----------+--------------| | 1001 | Brian | 1 | Sunday Roast | | 1002 | Rambo | 0 | Airline food | | 1003 | BamBam | 1 | Sunday Roast | | 1004 | Lazy | 0 | Airline food | +---------+-----------+-----------+--------------+
Vi kan se att lämpligt värde finns i Dinner
kolumn.
CASE
i en ORDER BY
Klausul
CASE
uttryck kan användas i alla påståenden eller satser som tillåter ett giltigt uttryck. Därför kan du använda den i satser som SELECT
, UPDATE
, DELETE
och SET
, och i satser som IN
, WHERE
, ORDER BY
, GROUP BY
, och HAVING
.
Använda en CASE
uttryck i en satss ORDER BY
klausul kan vara praktisk när du vill göra ett speciellt undantag för vissa värden när du beställer dina resultat.
Anta att vi kör följande fråga mot en tabell som innehåller musikgenrer.
SELECT Genre
FROM Genres
ORDER BY Genre ASC;
Resultat:
+---------+ | Genre | +---------+ | Blues | | Country | | Hip Hop | | Jazz | | Other | | Pop | | Punk | | Rap | | Rock | +---------+
Här sorterar vi resultaten efter Genre
kolumn, i stigande ordning.
Det här är bra förutom en sak. Genren som heter Other
. Skulle det inte vara trevligt om vi kunde flytta Other
till botten?
Vi kan uppnå detta med CASE
uttryck genom att ta ovanstående fråga och ändra den enligt följande.
SELECT Genre
FROM Genres
ORDER BY
CASE Genre
WHEN 'Other' THEN 1
ELSE 0
END
ASC, Genre ASC;
Resultat:
+---------+ | Genre | +---------+ | Blues | | Country | | Hip Hop | | Jazz | | Pop | | Punk | | Rap | | Rock | | Other | +---------+
COALESCE()
och NULLIF()
Funktioner
Beroende på scenariot kan vi använda funktioner som COALESCE()
och NULLIF()
som en genväg istället för att använda CASE
uttryck.
Dessa två funktioner är SQL-standard, och de fungerar enligt följande:
NULLIF (V1, V2)
Motsvarar:
CASE WHEN V1=V2 THEN NULL ELSE V1 END
Och:
COALESCE (V1, V2)
Motsvarar:
CASE WHEN V1 IS NOT NULL THEN V1 ELSE V2 END
Även:
COALESCE (V1, V2, ..., Vn)
Motsvarar:
CASE WHEN V1 IS NOT NULL THEN V1 ELSE COALESCE (V2, ..., Vn) END