In SQL, il CASE
istruzione valuta un elenco di condizioni e restituisce una delle più possibili espressioni di risultato.
In un certo senso, l'SQL CASE
è un po' simile all'istruzione IF...ELSE
affermazione in quanto ci consente di verificare una data condizione e restituire un risultato diverso a seconda del risultato.
È un CASE
Dichiarazione o CASE
Espressione?
In SQL, a volte le cose vengono chiamate "dichiarazioni" quando in realtà sono qualcos'altro. L'SQL "CASE
dichiarazione” è un esempio calzante (scusate il gioco di parole!).
Il CASE
è indicato nello standard SQL (ISO/IEC 9075) come CASE
espressione . Il suo scopo è “specificare un valore condizionale”.
Tuttavia, alcuni DBMS distinguono tra CASE
dichiarazione e il CASE
espressione e hanno una sintassi leggermente diversa per ciascuno. Ad esempio, sia MySQL che MariaDB forniscono il CASE
dichiarazione e il CASE
operatore come due caratteristiche distinte, ciascuna con una sintassi leggermente diversa.
CASE
Formati
In SQL, ci sono due formati di CASE
espressione:
- Semplice
CASE
espressione - Cercato
CASE
espressione
Di seguito sono riportati esempi di ciascuno.
Il semplice CASE
Espressione
Il semplice CASE
expression confronta un'espressione con un insieme di espressioni semplici per determinare il risultato.
Esempio:
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;
Risultato:
Grass
Questo esempio è stato eseguito in MySQL, ma l'attuale CASE
l'espressione dovrebbe funzionare sulla maggior parte dei principali RDBMS.
In questo esempio, il mio CASE
espressione fa parte di un SELECT
dichiarazione. Verifica tre condizioni e ha un ELSE
per soddisfare tutto ciò che non è coperto dalle tre condizioni.
In questo caso, l'animale Cow
corrisponde al terzo WHEN
espressione e l'espressione fornita dal relativo THEN
viene restituito.
Per essere chiari, il vero CASE
l'espressione è questa parte:
CASE @animal
WHEN 'Bird' THEN 'Seed'
WHEN 'Dog' THEN 'Beef'
WHEN 'Cow' THEN 'Grass'
ELSE 'Leftovers'
END
Quale CASE
non resta che controllare il valore di ogni WHEN
espressione contro l'espressione di input. In questo esempio, il @animal
variabile è l'espressione di input. Pertanto, sta verificando il valore di ogni WHEN
espressione contro @animal
variabile.
Quando/se trova una corrispondenza, restituisce l'espressione fornita dal corrispondente THEN
.
Il mio esempio usa tre WHEN
espressioni, ma avrei potuto usarne di più e avrei potuto usarne di meno, a seconda delle esigenze.
Il CASE
cercato Espressione
Il CASE
cercato expression valuta un insieme di espressioni booleane per determinare il risultato.
Ecco un esempio di un CASE
cercato espressione.
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;
Risultato:
Well done!
Il CASE
cercato espressione non ha un'espressione di input come il semplice CASE
espressione.
Lo ricorderai nel nostro semplice CASE
espressione, è iniziato con CASE
@animal
, e quindi sapevamo che il WHEN
le espressioni stavano tutte valutando rispetto al valore di @animal
.
Con il CASE
cercato espressione, all'inizio non forniamo un'espressione di input in questo modo. Invece, ogni WHEN
expression include un'espressione booleana per la quale essere valutata.
Un esempio di database
Ecco un esempio che dimostra come il CASE
l'espressione può essere utilizzata all'interno di una query di database.
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;
Risultato:
+---------------+------------+------------+ | 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 | +---------------+------------+------------+
Questo esempio utilizza un CASE
cercato espressione per valutare i risultati dalla Population
colonna della City
tavolo.
ELSE
è facoltativo
Il ELSE
l'argomento è facoltativo. Se omettiamo ELSE
e nessuna delle condizioni viene attivata, il risultato è NULL
.
Ecco cosa succede quando omettiamo ELSE
clausola dell'esempio precedente:
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;
Risultato:
+---------------+------------+-----------+ | 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
in un UPDATE
Dichiarazione
Aggiungiamo una colonna a City
tabella dell'esempio precedente:
ALTER TABLE City
ADD COLUMN Size VARCHAR(30) AFTER Population;
SELECT * FROM City
LIMIT 10;
Ecco come appare ora:
+----+----------------+-------------+---------------+------------+------+ | 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 | +----+----------------+-------------+---------------+------------+------+
Non abbiamo inserito alcun dato nella nuova Size
colonna, quindi restituisce NULL
in ogni riga.
Ora possiamo usare un CASE
espressione per aggiornare il Size
colonna con un valore che dipende dal valore nella Population
colonna:
UPDATE City
SET Size =
CASE
WHEN Population > 2000000 THEN 'Huge City'
WHEN Population >= 1000000 AND Population < 2000000 THEN 'Big City'
ELSE 'Small City'
END;
Ora selezioniamo i dati dalla tabella:
SELECT * FROM City
WHERE CountryCode = 'USA'
ORDER BY Population DESC
LIMIT 20;
Risultato:
+------+---------------+-------------+---------------+------------+------------+ | 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
in un INSERT
Dichiarazione
Supponiamo di avere la seguente tabella in un database di SQL Server:
+---------+-----------+-----------+--------------+ | DogId | DogName | GoodDog | Dinner | |---------+-----------+-----------+--------------| | 1001 | Brian | 1 | Sunday Roast | | 1002 | Rambo | 0 | Airline food | | 1003 | BamBam | 1 | Sunday Roast | +---------+-----------+-----------+--------------+
Inseriamo una nuova riga in quella tabella. Ma usiamo il CASE
espressione per inserire il valore appropriato nella Dinner
colonna, a seconda del valore in GoodDog
colonna:
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
);
Qui, il CASE
expression ha valutato il valore di una variabile che avevamo appena impostato, quindi ha inserito il valore appropriato nella Dinner
colonna.
Ora controlliamo di nuovo la tabella:
SELECT * FROM Dogs;
Risultato:
+---------+-----------+-----------+--------------+ | DogId | DogName | GoodDog | Dinner | |---------+-----------+-----------+--------------| | 1001 | Brian | 1 | Sunday Roast | | 1002 | Rambo | 0 | Airline food | | 1003 | BamBam | 1 | Sunday Roast | | 1004 | Lazy | 0 | Airline food | +---------+-----------+-----------+--------------+
Possiamo vedere che il valore appropriato è in Dinner
colonna.
CASE
in un ORDER BY
Clausola
Il CASE
L'espressione può essere utilizzata in qualsiasi istruzione o clausola che consenta un'espressione valida. Pertanto, puoi usarlo in istruzioni come SELECT
, UPDATE
, DELETE
e SET
e in clausole come IN
, WHERE
, ORDER BY
, GROUP BY
e HAVING
.
Utilizzando un CASE
espressione in un ORDER BY
di un'istruzione La clausola può essere utile quando si desidera fare un'eccezione speciale per determinati valori quando si ordinano i risultati.
Supponiamo di eseguire la seguente query su una tabella contenente generi musicali.
SELECT Genre
FROM Genres
ORDER BY Genre ASC;
Risultato:
+---------+ | Genre | +---------+ | Blues | | Country | | Hip Hop | | Jazz | | Other | | Pop | | Punk | | Rap | | Rock | +---------+
Qui ordiniamo i risultati in base al Genre
colonna, in ordine crescente.
Questo va bene tranne per una cosa. Il genere chiamato Other
. Non sarebbe bello se potessimo spostare Other
fino in fondo?
Possiamo raggiungere questo obiettivo con il CASE
espressione prendendo la query precedente e modificandola come segue.
SELECT Genre
FROM Genres
ORDER BY
CASE Genre
WHEN 'Other' THEN 1
ELSE 0
END
ASC, Genre ASC;
Risultato:
+---------+ | Genre | +---------+ | Blues | | Country | | Hip Hop | | Jazz | | Pop | | Punk | | Rap | | Rock | | Other | +---------+
Il COALESCE()
e NULLIF()
Funzioni
A seconda dello scenario possiamo utilizzare funzioni come COALESCE()
e NULLIF()
come scorciatoia, invece di usare il CASE
espressione.
Queste due funzioni sono standard SQL e funzionano come segue:
NULLIF (V1, V2)
Equivale a:
CASE WHEN V1=V2 THEN NULL ELSE V1 END
E:
COALESCE (V1, V2)
Equivale a:
CASE WHEN V1 IS NOT NULL THEN V1 ELSE V2 END
Inoltre:
COALESCE (V1, V2, ..., Vn)
Equivale a:
CASE WHEN V1 IS NOT NULL THEN V1 ELSE COALESCE (V2, ..., Vn) END