V SQL, CASE
příkaz vyhodnotí seznam podmínek a vrátí jeden z více možných výsledných výrazů.
V některých ohledech CASE
SQL příkaz je podobný příkazu IF...ELSE
prohlášení v tom, že nám umožňuje zkontrolovat danou podmínku a vrátit jiný výsledek v závislosti na výsledku.
Je to CASE
Prohlášení nebo CASE
Výraz?
V SQL se někdy věci označují jako „příkaz“, i když ve skutečnosti jde o něco jiného. SQL „CASE
statement“ je názorným příkladem (omlouvám se za slovní hříčku!).
CASE
příkaz je ve standardu SQL (ISO/IEC 9075) označován jako CASE
výraz . Jeho účelem je „specifikovat podmíněnou hodnotu“.
Některé DBMS však rozlišují mezi CASE
a CASE
výraz a mají pro každý trochu jinou syntaxi. Například MySQL i MariaDB poskytují CASE
a CASE
operátor jako dvě odlišné funkce, každá s mírně odlišnou syntaxí.
CASE
Formáty
V SQL existují dva formáty CASE
výraz:
- Jednoduchý
CASE
výraz - Hledali jste
CASE
výraz
Níže jsou uvedeny příklady každého z nich.
Jednoduchý CASE
Výraz
Jednoduchý CASE
výraz porovnává výraz se sadou jednoduchých výrazů a určuje výsledek.
Příklad:
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;
Výsledek:
Grass
Tento příklad byl proveden v MySQL, ale skutečný CASE
výraz by měl fungovat ve většině hlavních RDBMS.
V tomto příkladu můj CASE
výraz je součástí SELECT
prohlášení. Kontroluje tři podmínky a má ELSE
uspokojit vše, co není zahrnuto ve třech podmínkách.
V tomto případě zvíře Cow
odpovídá třetímu WHEN
výraz a výraz poskytnutý jeho THEN
je vráceno.
Aby bylo jasno, skutečný CASE
výraz je tato část:
CASE @animal
WHEN 'Bird' THEN 'Seed'
WHEN 'Dog' THEN 'Beef'
WHEN 'Cow' THEN 'Grass'
ELSE 'Leftovers'
END
Jaký CASE
zkontroluje hodnotu každého WHEN
výraz proti vstupnímu výrazu. V tomto příkladu @animal
proměnná je vstupní výraz. Proto kontroluje hodnotu každého WHEN
výraz proti @animal
proměnná.
Když/pokud najde shodu, vrátí výraz poskytnutý odpovídajícím THEN
.
Můj příklad používá tři WHEN
výrazů, ale mohl jsem použít více a mohl jsem použít méně, v závislosti na požadavcích.
Hledaný CASE
Výraz
Hledaný CASE
expression vyhodnotí sadu booleovských výrazů k určení výsledku.
Zde je příklad hledaného CASE
výraz.
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;
Výsledek:
Well done!
Hledaný CASE
výraz nemá vstupní výraz jako jednoduchý CASE
výraz.
Připomenete si to v našem jednoduchém CASE
výraz, začalo to CASE
@animal
, a proto jsme věděli, že WHEN
všechny výrazy byly vyhodnoceny oproti hodnotě @animal
.
S hledaným CASE
výraz, neposkytujeme vstupní výraz na začátku, jako je tento. Místo toho každý WHEN
výraz obsahuje booleovský výraz, pro který má být vyhodnocen.
Příklad databáze
Zde je příklad, který ukazuje, jak CASE
výraz lze použít v databázovém dotazu.
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;
Výsledek:
+---------------+------------+------------+ | 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 | +---------------+------------+------------+
Tento příklad používá hledaný CASE
výraz pro vyhodnocení výsledků z Population
ve sloupci City
stůl.
ELSE
je volitelný
ELSE
argument je volitelný. Pokud vynecháme ELSE
a není spuštěna žádná z podmínek, výsledkem je NULL
.
Co se stane, když vynecháme ELSE
klauzule z předchozího příkladu:
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;
Výsledek:
+---------------+------------+-----------+ | 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
v UPDATE
Prohlášení
Pojďme přidat sloupec do City
tabulka z předchozího příkladu:
ALTER TABLE City
ADD COLUMN Size VARCHAR(30) AFTER Population;
SELECT * FROM City
LIMIT 10;
Tady je to, jak to teď vypadá:
+----+----------------+-------------+---------------+------------+------+ | 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 | +----+----------------+-------------+---------------+------------+------+
Do nové Size
jsme nevložili žádná data sloupec, takže vrátí NULL
v každém řádku.
Nyní můžeme použít CASE
výraz pro aktualizaci Size
sloupec s hodnotou, která závisí na hodnotě v Population
sloupec:
UPDATE City
SET Size =
CASE
WHEN Population > 2000000 THEN 'Huge City'
WHEN Population >= 1000000 AND Population < 2000000 THEN 'Big City'
ELSE 'Small City'
END;
Nyní vybereme data z tabulky:
SELECT * FROM City
WHERE CountryCode = 'USA'
ORDER BY Population DESC
LIMIT 20;
Výsledek:
+------+---------------+-------------+---------------+------------+------------+ | 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
v INSERT
Prohlášení
Předpokládejme, že máme v databázi SQL Serveru následující tabulku:
+---------+-----------+-----------+--------------+ | DogId | DogName | GoodDog | Dinner | |---------+-----------+-----------+--------------| | 1001 | Brian | 1 | Sunday Roast | | 1002 | Rambo | 0 | Airline food | | 1003 | BamBam | 1 | Sunday Roast | +---------+-----------+-----------+--------------+
Vložíme do této tabulky nový řádek. Ale použijme CASE
výraz pro vložení příslušné hodnoty do Dinner
v závislosti na hodnotě v GoodDog
sloupec:
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
);
Zde je CASE
výraz vyhodnotil hodnotu proměnné, kterou jsme právě nastavili, a poté vložil příslušnou hodnotu do Dinner
sloupec.
Nyní znovu zkontrolujeme tabulku:
SELECT * FROM Dogs;
Výsledek:
+---------+-----------+-----------+--------------+ | DogId | DogName | GoodDog | Dinner | |---------+-----------+-----------+--------------| | 1001 | Brian | 1 | Sunday Roast | | 1002 | Rambo | 0 | Airline food | | 1003 | BamBam | 1 | Sunday Roast | | 1004 | Lazy | 0 | Airline food | +---------+-----------+-----------+--------------+
Vidíme, že příslušná hodnota je v Dinner
sloupec.
CASE
v ORDER BY
Ustanovení
CASE
výraz lze použít v jakémkoli příkazu nebo klauzuli, která umožňuje platný výraz. Proto jej můžete použít v příkazech jako SELECT
, UPDATE
, DELETE
a SET
a v klauzulích jako IN
, WHERE
, ORDER BY
, GROUP BY
a HAVING
.
Pomocí CASE
výraz v příkazu ORDER BY
klauzule může být užitečná, když chcete při řazení výsledků udělat zvláštní výjimku pro určité hodnoty.
Předpokládejme, že spustíme následující dotaz proti tabulce obsahující hudební žánry.
SELECT Genre
FROM Genres
ORDER BY Genre ASC;
Výsledek:
+---------+ | Genre | +---------+ | Blues | | Country | | Hip Hop | | Jazz | | Other | | Pop | | Punk | | Rap | | Rock | +---------+
Zde seřadíme výsledky podle Genre
sloupec, ve vzestupném pořadí.
To je fajn, až na jednu věc. Žánr s názvem Other
. Nebylo by hezké, kdybychom mohli přesunout Other
na dno?
Toho můžeme dosáhnout pomocí CASE
výraz tím, že vezmete výše uvedený dotaz a upravíte jej následovně.
SELECT Genre
FROM Genres
ORDER BY
CASE Genre
WHEN 'Other' THEN 1
ELSE 0
END
ASC, Genre ASC;
Výsledek:
+---------+ | Genre | +---------+ | Blues | | Country | | Hip Hop | | Jazz | | Pop | | Punk | | Rap | | Rock | | Other | +---------+
COALESCE()
a NULLIF()
Funkce
V závislosti na scénáři můžeme použít funkce jako COALESCE()
a NULLIF()
jako zkratku namísto použití CASE
výraz.
Tyto dvě funkce jsou standardem SQL a fungují následovně:
NULLIF (V1, V2)
Je ekvivalentní:
CASE WHEN V1=V2 THEN NULL ELSE V1 END
A:
COALESCE (V1, V2)
Je ekvivalentní:
CASE WHEN V1 IS NOT NULL THEN V1 ELSE V2 END
Také:
COALESCE (V1, V2, ..., Vn)
Je ekvivalentní:
CASE WHEN V1 IS NOT NULL THEN V1 ELSE COALESCE (V2, ..., Vn) END