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

Uso de expresiones CASE en SQL Server

Introducción

Las expresiones CASE en SQL Server se utilizan para la sustitución de valores de columna para presentar los conjuntos de resultados de una manera particular o consultas simples. Los casos de uso para tales comandos son varios.

Por ejemplo, hay una columna que contiene el código de departamento, pero desea mostrar el nombre del departamento en lugar del código. Puede lograrlo haciendo un JOIN con otra tabla que contenga los detalles del departamento. Sin embargo, supongamos que desea mantener la consulta relativamente simple. Otro caso de uso sería devolver valores específicos para el conjunto de valores calculados. Las columnas calculadas no encajarían si los conjuntos de condiciones para especificar no son los mismos.

Por lo general, las expresiones CASE de SQL Server tienen el formato que se muestra en el Listado 1.

-- Listing 1: CASE Expression Syntax
-- Simple CASE Expression
SELECT 
  col1
, col2
, CASE col3
WHEN 'a' THEN 'xxx'
WHEN 'b' THEN 'yyy'
WHEN 'c' THEN 'zzz'
ELSE 'Invalid Value'
END AS col3_name
FROM table_name;

-- Searched CASE Expression
SELECT 
  col1
, col2
, CASE
WHEN col3 = 1 THEN 'xxx'
WHEN col3 BETWEEN 2 and 9 THEN 'yyy'
WHEN col3 > 10 THEN 'zzz'
ELSE 'Invalid Value'
END AS col3_name
FROM table_name;

Caso simple y Caso buscado

Los dos escenarios descritos anteriormente encajan muy bien en los dos tipos de expresiones CASE disponibles en SQL Server. Una expresión CASE simple solo permite verificaciones de igualdad. Una expresión CASE buscada permite incluso expresiones booleanas.

Tenga en cuenta que los resultados de una expresión CASE caben en una sola columna. Además, observe que especificamos el nombre de la columna justo después de la cláusula CASE en la expresión CASE simple. Sin embargo, en la expresión CASE buscada, debemos especificar el nombre de columna para cada expresión booleana. Exploremos algunos ejemplos.

Entorno del escenario

En nuestra exploración de la expresión CASE, utilizaremos la conocida base de datos de ejemplo WideWorldImporters. Allí, usaremos el Sales.CustomerTransactions tabla para demostrar varios escenarios de la aplicación de expresión CASE. Como es común con T-SQL, es posible obtener resultados similares usando otras técnicas, como JOIN, pero nos enfocamos en una tabla para mostrar las capacidades de expresión CASE.

Tenga en cuenta que uno debe comprender los datos manejados para usar expresiones CASE. Por ejemplo, debemos saber lo que cada cliente código significa representar los datos con más sentido para el usuario final. En nuestros casos, podemos obtener la información de otras tablas.

El Listado 2 es una consulta simple que muestra cómo se ven los datos en la tabla. La Figura 1 nos muestra una porción de salida.

-- Listing 2: Data Set in Sales.CustomerTransactions
SELECT TOP (1000) [CustomerTransactionID]
      , [CustomerID]
      , [TransactionTypeID]
      , [InvoiceID]
      , [PaymentMethodID]
      , [TransactionDate]
      , [AmountExcludingTax]
      , [TaxAmount]
      , [TransactionAmount]
      , [OutstandingBalance]
      , [FinalizationDate]
      , [IsFinalized]
      , [LastEditedBy]
      , [LastEditedWhen]
  FROM [WideWorldImporters].[Sales].[CustomerTransactions] ;

Devolución de nombres de clientes basados ​​en ID de cliente

En este ejemplo, queremos mostrar el nombre de cada cliente según el código de cliente. Obtenemos los nombres de los clientes de otra tabla mediante una consulta JOIN. Nuevamente, estamos usando la expresión CASE para demostrar lo que puede hacer este enfoque.

-- Listing 3a: Determine Names Using a Join
select distinct top 10 b.CustomerID, a.CustomerName
from Sales.Customers a,Sales.CustomerTransactions b
where a.CustomerID = b.CustomerID;
-- Listing 3b: Determine Names Using a Join (Alternative)
select distinct top 10 b.CustomerID, a.CustomerName
from Sales.Customers a
inner join Sales.CustomerTransactions b
on a.CustomerID = b.CustomerID;

Con esta información, escribimos una consulta CASE simple para recuperar datos solo de Sales.CustomerTransactions (consulte el Listado 4). La Figura 3 resalta los nombres devueltos por la consulta.

Observe la aparición de 'Clientes desconocidos' en la salida. En el sentido real, estos clientes no son desconocidos. No los tenemos porque no atendemos su CustomerID en nuestra expresión CASE. Esto refuerza la necesidad de comprender los datos cuando se utilizan expresiones CASE.

-- Listing 4: Simple CASE Expression for Customer Name
SELECT TOP (20) 
CASE CustomerID 
	WHEN 1 THEN 'Tailspin Toys'
	WHEN 401 THEN 'Wingtip Toys'
	WHEN 801 THEN 'Eric Torres'
	WHEN 802 THEN 'Cosmina Vlad'
	WHEN 803 THEN 'Bala Dixit'
	WHEN 804 THEN 'Alekxandrs Reikstins'
	WHEN 805 THEN 'Ratan Podder'
	WHEN 806 THEN 'Shi Tu'
	WHEN 807 THEN 'Gunnar Lohmus'
	WHEN 808 THEN 'Jackson Kolios'
ELSE 'Unknown Customer'
END CustomerName
      , [InvoiceID]
      , [TransactionDate]
      , [TransactionAmount]
      , [OutstandingBalance]
      , [IsFinalized]
	  , [FinalizationDate]
      , [LastEditedBy]
      , [LastEditedWhen]
  FROM [WideWorldImporters].[Sales].[CustomerTransactions];

Devolver la clase de cliente según el monto de la transacción

En este ejemplo, usamos la expresión CASE de búsqueda para mostrar cuál de nuestros clientes tiene más valor con respecto al valor de la transacción.

Clasificamos a los clientes en tres grupos:regular, plata, oro y platino, según el valor de la transacción. Por supuesto, esto es simplista. En un escenario del mundo real, necesitaríamos sumar sus transacciones durante un período determinado. En este caso, estamos usando solo un subconjunto de datos para mostrar las capacidades de CASE Expression.

-- Listing 5: Searched Case Expression for Customer Class 
SELECT TOP (20) 
CASE CustomerID 
	WHEN 1 THEN 'Tailspin Toys'
	WHEN 401 THEN 'Wingtip Toys'
	WHEN 801 THEN 'Eric Torres'
	WHEN 802 THEN 'Cosmina Vlad'
	WHEN 803 THEN 'Bala Dixit'
	WHEN 804 THEN 'Alekxandrs Reikstins'
	WHEN 805 THEN 'Ratan Podder'
	WHEN 806 THEN 'Shi Tu'
	WHEN 807 THEN 'Gunnar Lohmus'
	WHEN 808 THEN 'Jackson Kolios'
ELSE 'Unknown Customer'
END CustomerName
      	, [InvoiceID]
	, [TransactionDate] 
, CASE  
	WHEN [TransactionAmount] BETWEEN 100 AND 1000 THEN 'Silver Customer'
	WHEN [TransactionAmount] BETWEEN 1000 AND 3000 THEN 'Gold Customer'
	WHEN [TransactionAmount] >= 3000 THEN 'Platinum Customer'
	ELSE 'Regular Customer'
	END AS CustomerClass
, [OutstandingBalance]
      	, [IsFinalized]
	  , [FinalizationDate]
      	, [LastEditedBy]
      	, [LastEditedWhen]
  FROM [WideWorldImporters].[Sales].[CustomerTransactions];

Devolver el día de la semana usando expresiones CASE anidadas

Procedemos con las muestras agregando una muestra que nos dice qué día de la semana fue la Fecha de transacción (consulte el Listado 6). Tenga en cuenta que podríamos haber logrado esto usando una forma mucho más simple de la consulta usando la función DATENAME en lugar de la función DATEPART.

-- Listing 6: Case Expression for Day of Week Using A Function  
SELECT TOP (20) 
CASE CustomerID 
	WHEN 1 THEN 'Tailspin Toys'
	WHEN 401 THEN 'Wingtip Toys'
	WHEN 801 THEN 'Eric Torres'
	WHEN 802 THEN 'Cosmina Vlad'
	WHEN 803 THEN 'Bala Dixit'
	WHEN 804 THEN 'Alekxandrs Reikstins'
	WHEN 805 THEN 'Ratan Podder'
	WHEN 806 THEN 'Shi Tu'
	WHEN 807 THEN 'Gunnar Lohmus'
	WHEN 808 THEN 'Jackson Kolios'
ELSE 'Unknown Customer'
END CustomerName
      , [InvoiceID]
, CASE  
	WHEN DATEPART(WEEKDAY,[TransactionDate]) = 1 THEN 'Sunday'
	WHEN DATEPART(WEEKDAY,[TransactionDate]) = 2 THEN 'Monday'
	WHEN DATEPART(WEEKDAY,[TransactionDate]) = 3 THEN 'Tuesday'
	WHEN DATEPART(WEEKDAY,[TransactionDate]) = 4 THEN 'Wednesday'
	WHEN DATEPART(WEEKDAY,[TransactionDate]) = 5 THEN 'Thursday'
	WHEN DATEPART(WEEKDAY,[TransactionDate]) = 6 THEN 'Friday'
	WHEN DATEPART(WEEKDAY,[TransactionDate]) = 7 THEN 'Saturday'
	END AS [Day of Week]
, CASE  
	WHEN [TransactionAmount] BETWEEN 100 AND 1000 THEN 'Silver Customer'
	WHEN [TransactionAmount] BETWEEN 1000 AND 3000 THEN 'Gold Customer'
	WHEN [TransactionAmount] >= 3000 THEN 'Platinum Customer'
	ELSE 'Regular Customer'
	END AS CustomerClass
	  , [OutstandingBalance]
      , [IsFinalized]
	  , [FinalizationDate]
      , [LastEditedBy]
      , [LastEditedWhen]
  FROM [WideWorldImporters].[Sales].[CustomerTransactions];

Etiquetado de transacciones según la fecha

Con el código de los Listados 7 y 8, podemos etiquetar las transacciones en función de la diferencia entre la fecha actual y la fecha de la transacción. También se aplica a la diferencia entre la fecha de la transacción y otra columna. Por lo tanto, podemos introducir columnas distintas a aquellas con las que estamos trabajando como entrada a una expresión booleana.

  -- Listing 7: Case Expression for Transaction by Comparing Two “Columns”
SELECT TOP (20) 
CASE CustomerID 
	WHEN 1 THEN 'Tailspin Toys'
	WHEN 401 THEN 'Wingtip Toys'
	WHEN 801 THEN 'Eric Torres'
	WHEN 802 THEN 'Cosmina Vlad'
	WHEN 803 THEN 'Bala Dixit'
	WHEN 804 THEN 'Alekxandrs Reikstins'
	WHEN 805 THEN 'Ratan Podder'
	WHEN 806 THEN 'Shi Tu'
	WHEN 807 THEN 'Gunnar Lohmus'
	WHEN 808 THEN 'Jackson Kolios'
ELSE 'Unknown Customer'
END CustomerName
      , [InvoiceID]
, CASE  
	WHEN DATEDIFF(DAY,[TransactionDate],GETDATE()) < 30 THEN 'Current Transaction'
	WHEN DATEDIFF(DAY,[TransactionDate],GETDATE()) BETWEEN 30 AND 90 THEN 'Old Transaction'
	WHEN DATEDIFF(DAY,[TransactionDate],GETDATE()) BETWEEN 90 AND 365 THEN 'Stale Transaction'
	WHEN DATEDIFF(DAY,[TransactionDate],GETDATE()) >= 365 THEN 'Archived Transaction'
	END AS [Transaction Age]
, CASE  
	WHEN [TransactionAmount] BETWEEN 100 AND 1000 THEN 'Silver Customer'
	WHEN [TransactionAmount] BETWEEN 1000 AND 3000 THEN 'Gold Customer'
	WHEN [TransactionAmount] >= 3000 THEN 'Platinum Customer'
	ELSE 'Regular Customer'
	END AS CustomerClass
	  , [OutstandingBalance]
      , [IsFinalized]
	  , [FinalizationDate]
      , [LastEditedBy]
      , [LastEditedWhen]
  FROM [WideWorldImporters].[Sales].[CustomerTransactions];
-- Listing 8: Case Expression for Transaction by Comparing Two Columns  
SELECT TOP (20) 
CASE CustomerID 
	WHEN 1 THEN 'Tailspin Toys'
	WHEN 401 THEN 'Wingtip Toys'
	WHEN 801 THEN 'Eric Torres'
	WHEN 802 THEN 'Cosmina Vlad'
	WHEN 803 THEN 'Bala Dixit'
	WHEN 804 THEN 'Alekxandrs Reikstins'
	WHEN 805 THEN 'Ratan Podder'
	WHEN 806 THEN 'Shi Tu'
	WHEN 807 THEN 'Gunnar Lohmus'
	WHEN 808 THEN 'Jackson Kolios'
ELSE 'Unknown Customer'
END CustomerName
      , [InvoiceID]
, CASE  
	WHEN DATEDIFF(DAY,[TransactionDate],[FinalizationDate]) < 30 THEN 'Prompt Transaction'
	WHEN DATEDIFF(DAY,[TransactionDate],[FinalizationDate]) BETWEEN 30 AND 90 THEN 'Delayed Transaction'
	WHEN DATEDIFF(DAY,[TransactionDate],[FinalizationDate]) BETWEEN 90 AND 365 THEN 'Serverely Delayed Transaction'
	WHEN DATEDIFF(DAY,[TransactionDate],[FinalizationDate]) >= 365 THEN 'Orphaned Transaction'
	END AS [Transaction Response]
, CASE  
	WHEN [TransactionAmount] BETWEEN 100 AND 1000 THEN 'Silver Customer'
	WHEN [TransactionAmount] BETWEEN 1000 AND 3000 THEN 'Gold Customer'
	WHEN [TransactionAmount] >= 3000 THEN 'Platinum Customer'
	ELSE 'Regular Customer'
	END AS CustomerClass
, [OutstandingBalance]
      	, [IsFinalized]
, [FinalizationDate]
      	, [LastEditedBy]
      	, [LastEditedWhen]
  FROM [WideWorldImporters].[Sales].[CustomerTransactions];

Expresiones CASE fuera de la lista SELECT

También podemos usar expresiones CASE en sentencias SET, sentencias UPDATE, cláusulas WHERE, cláusulas HAVING y cláusulas ORDER BY.

La instrucción Actualizar en el Listado 9 actualiza el Saldo pendiente columna de filas con cuatro ID de cliente diferentes que tienen valores diferentes. Esta declaración es equivalente a escribir cinco declaraciones de actualización diferentes para cada CASO y luego ELSE.

-- Listing 9: Update Statement with CASE Expression 
  UPDATE Sales.CustomerTransactions
  SET OutstandingBalance =
	(CASE 
		WHEN CustomerID = 832 THEN 100.00
		WHEN CustomerID = 803 THEN 150.00
		WHEN CustomerID = 905 THEN 200.00
		WHEN CustomerID = 976 THEN 70.00
		ELSE 50.00
	END
	);
	SELECT TOP 20 * FROM Sales.CustomerTransactions;

Conclusión

SQL y T-SQL le permiten sustituir valores almacenados en una columna con sus valores deseados. En este artículo, hemos explorado expresiones CASE simples y buscadas con ejemplos.

Las expresiones CASE se pueden usar en cláusulas SELECT, declaraciones SET, declaraciones UPDATE, cláusulas WHERE, HAVING y ORDER BY.

Referencias

CASO
Funciones de fecha y hora