sql >> Base de Datos >  >> RDS >> Sqlserver

Expresión CASE de SQL Server

En SQL Server, el T-SQL CASE expresión es una expresión escalar que devuelve un valor basado en lógica condicional. Evalúa una lista de condiciones y devuelve un valor, basado en el resultado de esas condiciones..

De alguna manera, el CASE de SQL Server expresión es similar a IF...ELSE . Sin embargo, CASE le permite verificar múltiples condiciones, mientras que IF...ELSE no.

Además, en SQL Server, IF...ELSE es una palabra clave de lenguaje de control de flujo, mientras que CASE no es. El CASE expresión no se puede utilizar para controlar el flujo de ejecución de instrucciones T-SQL, bloques de instrucciones, funciones definidas por el usuario y procedimientos almacenados.

Las 2 formas de expresión CASE

Hay dos formas de CASE expresión en SQL Server:

  • Simple CASE expresión
  • Buscado CASE expresión

Estos se explican con ejemplos a continuación.

Forma 1:la expresión CASE simple

El CASE simple expresión compara una expresión con un conjunto de expresiones simples para determinar el resultado.

Aquí hay un ejemplo básico para demostrar cómo un CASE expresión funciona en SQL Server.

DECLARE @stock_ticker varchar(4) = 'V';

SELECT Company =  
    CASE @stock_ticker  
        WHEN 'AAPL' THEN 'Apple'
        WHEN 'FB' THEN 'Facebook'
        WHEN 'V' THEN 'Visa'
        ELSE 'Not in the portfolio'  
    END

Resultado:

+-----------+
| Company   |
|-----------|
| Visa      |
+-----------+

En este ejemplo, mi CASE expresión es parte de un SELECT declaración. Comprueba tres condiciones y tiene un ELSE para atender lo que no esté contemplado en las tres condiciones.

En este caso, el tablero de cotizaciones V coincide con el tercer WHEN expresión, y la expresión proporcionada por THEN es devuelto.

Para ser claros, el CASE real expresión es esta parte:

    CASE @stock_ticker  
        WHEN 'AAPL' THEN 'Apple'
        WHEN 'FB' THEN 'Facebook'
        WHEN 'MA' THEN 'Mastercard'
        WHEN 'V' THEN 'Visa'
        ELSE 'Not in the portfolio'  
    END

¿Qué CASE lo que hace es comprobar el valor de cada WHEN expresión contra la expresión de entrada. En mi ejemplo, @stock_ticker variable es la expresión de entrada. Por lo tanto, está comprobando el valor de cada WHEN expresión contra el @stock_ticker variables.

Cuando/si encuentra una coincidencia, devuelve la expresión proporcionada por THEN .

Mi ejemplo usa tres WHEN expresiones, pero podría haber sido más y podría haber sido menos, dependiendo de mis requisitos.

Formulario 2:la expresión CASE buscada

El CASE buscado expresión evalúa un conjunto de expresiones booleanas para determinar el resultado.

Este es un ejemplo de un CASE buscado expresión.

DECLARE @price int = 1500;

SELECT Affordability =  
    CASE   
        WHEN @price < 100 THEN 'Cheap'
        WHEN @price >= 100 AND @price < 500 THEN 'Affordable'
        ELSE 'Expensive'  
    END

Resultado:

+-----------------+
| Affordability   |
|-----------------|
| Expensive       |
+-----------------+

Un CASE buscado expresión no tiene una expresión de entrada como el simple CASE expresión.

Lo recordarás en nuestro sencillo CASE expresión, comenzó con CASE @stock_ticker , y por lo tanto sabíamos que el WHEN todas las expresiones se evaluaron contra el valor de @stock_ticker .

Con el CASE buscado expresión, no proporcionamos una expresión de entrada al principio como esa. En cambio, cada WHEN expresión incluye una expresión booleana contra la cual se evaluará.

Un ejemplo de base de datos

Aquí hay un ejemplo que demuestra cómo CASE expresión se puede utilizar dentro de una consulta de base de datos.

USE WideWorldImporters;
SELECT 
    CityName AS [City], 
    LatestRecordedPopulation AS [Population], 
    Size =  
      CASE 
         WHEN LatestRecordedPopulation < 2000000 THEN 'Small City'  
         WHEN LatestRecordedPopulation >= 2000000 AND LatestRecordedPopulation < 3000000 THEN 'Big City' 
         ELSE 'Really Big City'
      END 
FROM Application.Cities
WHERE LatestRecordedPopulation > 1000000;

Resultado:

+--------------+--------------+-----------------+
| City         | Population   | Size            |
|--------------+--------------+-----------------|
| Brooklyn     | 2565635      | Big City        |
| Chicago      | 2695598      | Big City        |
| Dallas       | 1197816      | Small City      |
| Houston      | 2099451      | Big City        |
| Los Angeles  | 3792621      | Really Big City |
| Manhattan    | 1619090      | Small City      |
| New York     | 8175133      | Really Big City |
| Philadelphia | 1526006      | Small City      |
| Phoenix      | 1445632      | Small City      |
| Queens       | 2272771      | Big City        |
| San Antonio  | 1327407      | Small City      |
| San Diego    | 1307402      | Small City      |
| The Bronx    | 1408473      | Small City      |
+--------------+--------------+-----------------+

Este ejemplo utiliza un CASE buscado expresión para evaluar los resultados de LatestRecordedPopulation columna de Application.Cities mesa.

Tipos de datos

En SQL Server, el tipo de datos de la expresión de entrada y el WHEN las expresiones deben ser iguales o deben ser una conversión implícita.

Esto es lo que sucede si no lo son:

DECLARE @stock_ticker varchar(4) = 'V';

SELECT Company =  
      CASE @stock_ticker  
         WHEN 1 THEN 'Apple'
         WHEN 2 THEN 'Facebook'
         WHEN 3 THEN 'Mastercard'
         WHEN 4 THEN 'Visa'
         ELSE 'Not in the portfolio'  
      END

Resultado:

Msg 245, Level 16, State 1, Line 3
Conversion failed when converting the varchar value 'V' to data type int.

Orden de Evaluación

El T-SQL CASE expresión evalúa sus condiciones secuencialmente y se detiene con la primera condición cuya condición se cumple.

Para demostrar esto, usemos múltiples WHEN expresiones que comparten el mismo valor:

DECLARE @stock_ticker varchar(4) = 'V';

SELECT Company =  
    CASE @stock_ticker  
        WHEN 'V' THEN 'Visa 1'
        WHEN 'V' THEN 'Visa 2'
        WHEN 'V' THEN 'Visa 3'
        ELSE 'Not in the portfolio'  
    END

Resultado:

+-----------+
| Company   |
|-----------|
| Visa 1    |
+-----------+

En este caso, se detuvo en el primer WHEN expresión.

Puede haber un escenario ocasional en el que una expresión se evalúe antes que un CASE expresión recibe los resultados de la expresión como su entrada. En tales escenarios, podría terminar con un error. Esto podría suceder si incluye una expresión agregada como WHEN expresión.

Por este motivo, Microsoft aconseja que:

Solo debe depender del orden de evaluación de las condiciones CUANDO para las expresiones escalares (incluidas las subconsultas no correlacionadas que devuelven escalares), no para las expresiones agregadas.

ELSE es opcional

El ELSE argumento es opcional. Por lo tanto, podríamos reescribir nuestro ejemplo de "asequibilidad" de la siguiente manera:

DECLARE @price int = 1500;

SELECT Affordability =  
    CASE   
        WHEN @price < 100 THEN 'Cheap'
        WHEN @price >= 100 AND @price < 500 THEN 'Affordable'
        WHEN @price >= 500 THEN 'Expensive'
    END    

Resultado:

+-----------------+
| Affordability   |
|-----------------|
| Expensive       |
+-----------------+

Aunque tenga en cuenta que podría terminar con NULL si omite el ELSE argumento.

El siguiente ejemplo da como resultado NULL :

DECLARE @price int = 1500;

SELECT Affordability =  
    CASE   
        WHEN @price < 100 THEN 'Cheap'
        WHEN @price >= 100 AND @price < 500 THEN 'Affordable'
        WHEN @price >= 500 AND @price < 1000 THEN 'Expensive'
    END    

Resultado:

+-----------------+
| Affordability   |
|-----------------|
| NULL            |
+-----------------+

En tales casos, siempre podríamos agregar un ELSE argumento, por si acaso (¡perdón por el juego de palabras!):

DECLARE @price int = 1500;

SELECT Affordability =  
    CASE   
        WHEN @price < 100 THEN 'Cheap'
        WHEN @price >= 100 AND @price < 500 THEN 'Affordable'
        WHEN @price >= 500 AND @price < 1000 THEN 'Expensive'
        ELSE 'Unknown'
    END  

Resultado:

+-----------------+
| Affordability   |
|-----------------|
| Unknown         |
+-----------------+

Es cierto que este ejemplo es probablemente un poco artificial. Después de todo, no hay necesidad de limitar "caro". Si algo es caro por menos de $1000, también es caro si cuesta más de $1000.

Pero el punto es que puedes usar ELSE para detectar cualquier cosa que no esté cubierta por WHEN expresión/es.

Expresiones CASE anidadas

Puede anidar CASE expresiones si es necesario.

DECLARE @price int, @on_sale bit;
SET @price = 1500;
SET @on_sale = 1;

SELECT Affordability =  
    CASE   
        WHEN @price < 100 THEN 'Cheap'
        WHEN @price >= 100 THEN 
            CASE @on_sale
                WHEN 0 THEN 'Expensive (but it''s not currently on sale)' 
                WHEN 1 THEN 'Expensive (and it''s already on sale!)'
            END
    END

Resultado:

+---------------------------------------+
| Affordability                         |
|---------------------------------------|
| Expensive (and it's already on sale!) |
+---------------------------------------+

Sin embargo, es importante tener en cuenta que solo se permiten 10 niveles de anidamiento para CASE expresiones en SQL Server. Si intenta anidar más de 10 niveles, obtendrá un error.

CASO en una Cláusula ORDER BY

Como se mencionó, el T-SQL CASE expresión se puede utilizar en cualquier declaración o cláusula que permita una expresión válida. Por lo tanto, puede usarlo en declaraciones como SELECT , UPDATE , DELETE y SET , y en cláusulas como IN , WHERE , ORDER BY , GROUP BY , y HAVING .

Usando un CASE expresión en el ORDER BY de una declaración La cláusula puede ser útil cuando desea hacer una excepción especial para ciertos valores al ordenar sus resultados.

Supongamos que ejecutamos la siguiente consulta en una tabla que contiene géneros musicales.

SELECT Genre 
FROM MusicGenres
ORDER BY Genre ASC;

Resultado:

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

Aquí, ordenamos los resultados por Genre columna, en orden ascendente.

Esto está bien excepto por una cosa. El género llamado Otro . ¿No sería bueno si pudiéramos mover Otro hasta el fondo?

Podemos lograr esto con el CASE expresión tomando la consulta anterior y modificándola de la siguiente manera.

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

Resultado:

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

CASO en una instrucción UPDATE

Aquí hay un ejemplo del uso de un CASE expresión en un UPDATE declaración.

Supongamos que tenemos la siguiente tabla:

+---------+-----------+-----------+----------+
| DogId   | DogName   | GoodDog   | Dinner   |
|---------+-----------+-----------+----------|
| 1       | Fetch     | 1         | NULL     |
| 2       | Fluffy    | 0         | NULL     |
| 3       | Wag       | 0         | NULL     |
| 1001    | Brian     | 1         | NULL     |
| 1002    | Rambo     | 0         | NULL     |
| 1003    | BamBam    | 1         | NULL     |
+---------+-----------+-----------+----------+

Recientemente hemos añadido la Dinner columna, y sigue siendo NULL , esperando que se inserten valores.

Pero los valores a insertar dependerán del valor del GoodDog columna.

Podríamos usar un CASE expresión en tal escenario.

UPDATE Dogs 
SET Dinner = 
    CASE GoodDog
        WHEN 1 THEN 'Sunday Roast'
        ELSE 'Airline food'
    END

SELECT * FROM Dogs;

Resultado:

+---------+-----------+-----------+--------------+
| DogId   | DogName   | GoodDog   | Dinner       |
|---------+-----------+-----------+--------------|
| 1       | Fetch     | 1         | Sunday Roast |
| 2       | Fluffy    | 0         | Airline food |
| 3       | Wag       | 0         | Airline food |
| 1001    | Brian     | 1         | Sunday Roast |
| 1002    | Rambo     | 0         | Airline food |
| 1003    | BamBam    | 1         | Sunday Roast |
+---------+-----------+-----------+--------------+

CASO en una instrucción INSERT

Podemos tomar la tabla del ejemplo anterior e insertar un nuevo valor.

Y podemos volver a aprovechar el CASE expresión para insertar el valor apropiado en Dinner columna.

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

SELECT * FROM Dogs;

Resultado:

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

Esta vez el CASE expresión estaba evaluando el valor de una variable que acabábamos de establecer, luego insertaba el valor apropiado en el Dinner columna.

¿Es una instrucción CASE o una expresión CASE?

En SQL, muchas cosas se denominan "declaraciones" cuando, de hecho, son otra cosa. Esto también parece ser cierto para T-SQL “CASE declaración”.

Aunque a menudo se le conoce como el CASE declaración, es más exacto llamarlo CASE expresión . Así es también como se refiere la documentación de Microsoft.

En SQL Server, en lugar de ser una declaración en sí misma, CASE se puede usar en cualquier declaración o cláusula que permita una expresión válida. Una expresión es una combinación de símbolos y operadores que se evalúan para obtener un único valor de datos.

Sin embargo, algunos DBMS distinguen entre CASE declaración, y el CASE expresión, y tienen una sintaxis ligeramente diferente para cada uno. MySQL distingue entre el CASE declaración y el CASE operador, que es esencialmente el mismo que el CASE expresión.