Mysql
 sql >> Base de données >  >> RDS >> Mysql

Instruction SQL CASE

En SQL, le CASE évalue une liste de conditions et renvoie l'une des multiples expressions de résultat possibles.

D'une certaine manière, le SQL CASE l'instruction est un peu similaire à IF...ELSE déclaration en ce sens qu'elle nous permet de vérifier une condition donnée et de renvoyer un résultat différent en fonction du résultat.

Est-ce un CASE Instruction ou CASE Expression ?

En SQL, les choses sont parfois appelées "instructions" alors qu'en fait, elles sont autre chose. Le SQL "CASE déclaration" en est un exemple (désolé pour le jeu de mots !).

Le CASE l'instruction est référencée dans la norme SQL (ISO/IEC 9075) sous le nom de CASE expression . Son but est de "spécifier une valeur conditionnelle".

Cependant, certains SGBD font la distinction entre le CASE déclaration et le CASE expression, et ont une syntaxe légèrement différente pour chacun. Par exemple, MySQL et MariaDB fournissent le CASE déclaration et le CASE comme deux fonctionnalités distinctes, chacune avec une syntaxe légèrement différente.

CASE Formats

En SQL, il existe deux formats de CASE expression :

  • Simple CASE expression
  • Recherché CASE expression

Vous trouverez ci-dessous des exemples de chacun.

Le CASE simple Expression

Le simple CASE expression compare une expression à un ensemble d'expressions simples pour déterminer le résultat.

Exemple :

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;

Résultat :

Grass

Cet exemple a été fait dans MySQL, mais le réel CASE L'expression devrait fonctionner sur la plupart des principaux SGBDR.

Dans cet exemple, mon CASE l'expression fait partie d'un SELECT déclaration. Il vérifie trois conditions et a un ELSE pour répondre à tout ce qui n'est pas couvert dans les trois conditions.

Dans ce cas, l'animal Cow correspond au troisième WHEN expression, et l'expression fournie par son THEN est renvoyé.

Pour être clair, le véritable CASE expression est cette partie :

    CASE @animal  
        WHEN 'Bird' THEN 'Seed'
        WHEN 'Dog' THEN 'Beef'
        WHEN 'Cow' THEN 'Grass'
        ELSE 'Leftovers'  
    END

Quel CASE fait est de vérifier la valeur de chaque WHEN expression par rapport à l'expression d'entrée. Dans cet exemple, le @animal variable est l'expression d'entrée. Par conséquent, il vérifie la valeur de chaque WHEN expression contre le @animal variables.

Quand/s'il trouve une correspondance, il renvoie l'expression fournie par le THEN correspondant .

Mon exemple utilise trois WHEN expressions, mais j'aurais pu en utiliser plus et j'aurais pu en utiliser moins, selon les besoins.

Le CASE recherché Expression

Le CASE recherché expression évalue un ensemble d'expressions booléennes pour déterminer le résultat.

Voici un exemple de CASE recherché expression.

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;

Résultat :

Well done!

Le CASE recherché expression n'a pas d'expression d'entrée comme le simple CASE expression.

Vous vous souviendrez que dans notre simple CASE expression, il a commencé par CASE @animal , et donc nous savions que le WHEN les expressions étaient toutes évaluées par rapport à la valeur de @animal .

Avec le CASE recherché expression, nous ne fournissons pas une expression d'entrée au début comme ça. Au lieu de cela, chaque WHEN expression inclut une expression booléenne pour laquelle elle doit être évaluée.

Un exemple de base de données

Voici un exemple qui montre comment le CASE expression peut être utilisée dans une requête de base de données.

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;

Résultat :

+---------------+------------+------------+
| 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 |
+---------------+------------+------------+

Cet exemple utilise un CASE recherché expression pour évaluer les résultats de la Population colonne de la City table.

ELSE est Facultatif

Le ELSE l'argument est facultatif. Si nous omettons le ELSE , et aucune des conditions n'est déclenchée, le résultat est NULL .

Voici ce qui se passe lorsque nous omettons le ELSE clause de l'exemple précédent :

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;

Résultat :

+---------------+------------+-----------+
| 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 dans une UPDATE Déclaration

Ajoutons une colonne à la City tableau de l'exemple précédent :

ALTER TABLE City
ADD COLUMN Size VARCHAR(30) AFTER Population;

SELECT * FROM City
LIMIT 10;

Voici à quoi cela ressemble maintenant :

+----+----------------+-------------+---------------+------------+------+
| 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 |
+----+----------------+-------------+---------------+------------+------+

Nous n'avons inséré aucune donnée dans le nouveau Size colonne, elle renvoie donc NULL dans chaque rangée.

Nous pouvons maintenant utiliser un CASE expression pour mettre à jour la Size colonne avec une valeur qui dépend de la valeur dans la Population colonne :

UPDATE City 
SET Size = 
    CASE 
        WHEN Population > 2000000 THEN 'Huge City'  
        WHEN Population >= 1000000 AND Population < 2000000 THEN 'Big City'
        ELSE 'Small City'
    END;

Maintenant, sélectionnons des données dans le tableau :

SELECT * FROM City
WHERE CountryCode = 'USA'
ORDER BY Population DESC
LIMIT 20;

Résultat :

+------+---------------+-------------+---------------+------------+------------+
| 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 dans un INSERT Déclaration

Supposons que nous ayons la table suivante dans une base de données SQL Server :

+---------+-----------+-----------+--------------+
| DogId   | DogName   | GoodDog   | Dinner       |
|---------+-----------+-----------+--------------|
| 1001    | Brian     | 1         | Sunday Roast |
| 1002    | Rambo     | 0         | Airline food |
| 1003    | BamBam    | 1         | Sunday Roast |
+---------+-----------+-----------+--------------+

Insérons une nouvelle ligne dans ce tableau. Mais utilisons le CASE expression pour insérer la valeur appropriée dans le Dinner colonne, en fonction de la valeur dans la colonne GoodDog colonne :

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
    );

Ici, le CASE expression a évalué la valeur d'une variable que nous venions de définir, puis a inséré la valeur appropriée dans le Dinner colonne.

Maintenant, vérifions à nouveau le tableau :

SELECT * FROM Dogs;

Résultat :

+---------+-----------+-----------+--------------+
| DogId   | DogName   | GoodDog   | Dinner       |
|---------+-----------+-----------+--------------|
| 1001    | Brian     | 1         | Sunday Roast |
| 1002    | Rambo     | 0         | Airline food |
| 1003    | BamBam    | 1         | Sunday Roast |
| 1004    | Lazy      | 0         | Airline food |
+---------+-----------+-----------+--------------+

Nous pouvons voir que la valeur appropriée est dans le Dinner colonne.

CASE dans un ORDER BY Article

Le CASE expression peut être utilisée dans n'importe quelle instruction ou clause qui autorise une expression valide. Par conséquent, vous pouvez l'utiliser dans des instructions telles que SELECT , UPDATE , DELETE et SET , et dans des clauses telles que IN , WHERE , ORDER BY , GROUP BY , et HAVING .

Utiliser un CASE expression dans ORDER BY d'une instruction La clause peut être pratique lorsque vous souhaitez faire une exception spéciale pour certaines valeurs lors de la commande de vos résultats.

Supposons que nous lancions la requête suivante sur une table contenant des genres musicaux.

SELECT Genre 
FROM Genres
ORDER BY Genre ASC;

Résultat :

+---------+
| Genre   |
+---------+
| Blues   |
| Country |
| Hip Hop |
| Jazz    |
| Other   |
| Pop     |
| Punk    |
| Rap     |
| Rock    |
+---------+

Ici, nous classons les résultats par Genre colonne, par ordre croissant.

C'est bien sauf pour une chose. Le genre appelé Other . Ne serait-ce pas bien si nous pouvions déplacer Other vers le bas ?

Nous pouvons y parvenir avec le CASE expression en prenant la requête ci-dessus et en la modifiant comme suit.

SELECT Genre
FROM Genres
ORDER BY 
    CASE Genre
        WHEN 'Other' THEN 1
        ELSE 0
    END
    ASC, Genre ASC;

Résultat :

+---------+
| Genre   |
+---------+
| Blues   |
| Country |
| Hip Hop |
| Jazz    |
| Pop     |
| Punk    |
| Rap     |
| Rock    |
| Other   |
+---------+

Le COALESCE() et NULLIF() Fonctions

Selon le scénario, nous pouvons utiliser des fonctions telles que COALESCE() et NULLIF() comme raccourci, au lieu d'utiliser le CASE expression.

Ces deux fonctions sont au standard SQL et fonctionnent comme suit :

NULLIF (V1, V2)

Est équivalent à :

CASE WHEN V1=V2 THEN NULL ELSE V1 END

Et :

COALESCE (V1, V2)

Est équivalent à :

CASE WHEN V1 IS NOT NULL THEN V1 ELSE V2 END

Aussi :

COALESCE (V1, V2, ..., Vn)

Est équivalent à :

CASE WHEN V1 IS NOT NULL THEN V1 ELSE COALESCE (V2, ..., Vn) END