sql >> Databasteknik >  >> RDS >> Mysql

SQL CASE-sats

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

  1. Hur man byter namn på en databas i MySQL

  2. Matcha utbud med efterfrågan – lösningar, del 2

  3. Är COUNT(rovid) snabbare än COUNT(*)?

  4. Använder ORDER BY och GROUP BY tillsammans