Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Usando expressões CASE no SQL Server

Introdução


Expressões CASE no SQL Server são usadas para a substituição de valores de coluna para apresentar os conjuntos de resultados de uma forma específica ou consultas simples. Os casos de uso para tais comandos são vários.

Por exemplo, há uma coluna contendo o código do departamento, mas você deseja exibir o nome do departamento em vez do código. Você pode conseguir isso fazendo um JOIN com outra tabela contendo os detalhes do departamento. No entanto, vamos supor que você queira manter a consulta relativamente simples. Outro caso de uso seria retornar valores específicos para o conjunto de valores calculados. As colunas computadas não caberiam se os conjuntos de condições a serem especificados não fossem os mesmos.

Normalmente, as Expressões CASE do SQL Server têm o formato mostrado na Listagem 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 simples e caso pesquisado


Os dois cenários descritos acima se encaixam perfeitamente nos dois tipos de expressões CASE disponíveis no SQL Server. Uma expressão CASE simples permite apenas verificações de igualdade. Uma expressão CASE pesquisada permite até mesmo expressões booleanas.

Observe que os resultados de uma expressão CASE cabem em uma única coluna. Além disso, observe que especificamos o nome da coluna logo após a cláusula CASE na expressão Simple CASE. No entanto, na expressão CASE pesquisada, devemos especificar o nome da coluna para cada expressão booleana. Vamos explorar alguns exemplos.

Cenário Ambiente


Em nossa exploração da expressão CASE, usaremos o conhecido banco de dados de exemplo WideWorldImporters. Lá, usaremos as Sales.CustomerTransactions tabela para demonstrar vários cenários do aplicativo de expressão CASE. Como é comum com o T-SQL, é possível obter resultados semelhantes usando outras técnicas, como JOINs, mas focamos em uma tabela para mostrar os recursos da expressão CASE.

Observe que é preciso entender os dados manipulados para usar expressões CASE. Por exemplo, devemos saber o que cada cliente código significa representar os dados com mais sentido para o usuário final. Em nossos casos, podemos obter as informações de outras tabelas.

A Listagem 2 é uma consulta simples que mostra a aparência dos dados na tabela. A Figura 1 nos mostra uma parte de saída.
-- 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] ;

Retornando nomes de clientes com base no ID do cliente


Neste exemplo, queremos exibir o nome de cada cliente com base no código do cliente. Obtemos os nomes dos clientes de outra tabela usando uma consulta JOIN. Novamente, estamos usando a expressão CASE para demonstrar o que essa abordagem pode fazer.
-- 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;

Com essas informações, escrevemos uma consulta CASE simples para recuperar dados apenas de Sales.CustomerTransactions (consulte a Listagem 4). A Figura 3 destaca os nomes retornados pela consulta.

Observe a ocorrência de 'Clientes desconhecidos' na saída. No sentido real, esses clientes não são desconhecidos. Não os temos porque não atendemos ao CustomerID em nossa expressão CASE. Isso reforça a necessidade de entender os dados ao usar expressões 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];

Devolvendo a classe do cliente com base no valor da transação


Neste exemplo, usamos a expressão Searched CASE para mostrar qual de nossos clientes tem mais valor em relação ao valor da transação.

Classificamos os clientes em três grupos – Regular, Silver, Gold e Platinum, com base no valor da transação. Claro, isso é simplista. Em um cenário do mundo real, precisaríamos somar suas transações em um determinado período. Nesse caso, estamos usando apenas um subconjunto de dados para mostrar os recursos da 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];

Retornando o dia da semana usando expressões CASE aninhadas


Prosseguimos com as amostras adicionando uma amostra informando em que dia da semana foi a Data da Transação (consulte a Listagem 6). Observe que poderíamos ter conseguido isso usando uma forma muito mais simples de consulta usando a função DATENAME em vez da função 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];

Rotular transações com base na data


Usando o código nas Listagens 7 e 8, podemos rotular as transações com base na diferença entre a data atual e a data da transação. Também se aplica à diferença entre a data da transação e outra coluna. Portanto, podemos introduzir colunas diferentes daquelas com as quais estamos trabalhando como entrada para uma expressão 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];

Expressões CASE fora da lista SELECT


Também podemos usar expressões CASE em instruções SET, instruções UPDATE, cláusulas WHERE, cláusulas HAVING e cláusulas ORDER BY.

A instrução Update na Listagem 9 atualiza o OutstandingBalance coluna de linhas com quatro IDs de clientes diferentes com valores diferentes. Essa instrução é equivalente a escrever cinco instruções de atualização diferentes para cada CASE e, em seguida, o 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;

Conclusão


SQL e T-SQL permitem substituir valores armazenados em uma coluna pelos valores desejados. Neste artigo, exploramos expressões CASE simples e pesquisadas com exemplos.

As expressões CASE podem ser usadas em cláusulas SELECT, instruções SET, instruções UPDATE, cláusulas WHERE, HAVING e ORDER BY.

Referências


CASO
Funções de data e hora