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

Instrução SQL CASE:O que é e quais são as melhores maneiras de usá-lo?




Uma instrução SQL CASE avalia e retorna resultados com base em valores, predicados e condições particulares de acordo com a lógica definida. Por exemplo, suponha que você tenha uma tabela de eleitores com os seguintes detalhes:
  • Código de eleitor
  • Nome
  • DO

Se você estivesse procurando lógica sobre a elegibilidade de votação, isso dependeria dos valores na coluna DOB.

Se o eleitor tiver mais de 18 anos, ele poderá votar.



Vejamos outro exemplo. Muitas vezes, armazenamos os valores das colunas nos bits 1 ou 0. Digamos que você armazene os valores de disponibilidade de um produto como 1 ou 0. Por exemplo:
  • 1 =O produto está disponível
  • 0 =Produto esgotado

Se observarmos a perspectiva do banco de dados, é uma boa prática usar as abreviações ou bits sempre que possível. É benéfico para o otimizador de consultas do SQL Server na preparação do plano de execução otimizado. Mas, da perspectiva do aplicativo, o usuário final não exige esses valores. Os clientes só precisam ver se o produto está disponível ou não.

Na imagem abaixo, vemos a perspectiva do banco de dados e do aplicativo.


O que a instrução SQL CASE faz?


Uma instrução CASE no SQL Server avalia uma expressão e retorna um valor com base nas condições definidas. Portanto, no exemplo anterior, as instruções CASE funcionam conforme mostrado abaixo.



Em alto nível, a sintaxe de uma instrução SQL CASE é mostrada abaixo. Aqui, especificamos várias condições. O SQL Server avalia as condições sequencialmente. Assim que uma condição for avaliada com sucesso, ela interromperá a avaliação das condições restantes. Se nenhuma das condições for satisfeita, podemos usar uma instrução ELSE opcional para retornar o valor padrão. Por exemplo, se tivermos um valor diferente de 0 e 1 na coluna de disponibilidade, você obterá a saída do bloco de código ELSE. Requer pelo menos um conjunto de blocos WHEN e THEN. A instrução CASE deve terminar com o bloco END.



Vamos explorar a instrução SQL CASE usando vários exemplos.

Observação:neste artigo, usamos o banco de dados de exemplo da Microsoft, AdventureWorks. Você pode fazer o download do backup no Microsoft Docs.

A instrução SELECT com uma expressão CASE simples


Nesse tipo de instrução CASE, usamos expressões de verificação de igualdade. A consulta a seguir implementa uma expressão CASE simples.
  • Se o valor em [SalariedFlag] for 1, ele mostrará o Funcionário ativo
  • Para todos os outros valores, ele exibe a saída como Funcionário inativo
SELECT TOP 5 Nationalidnumber ,
CASE salariedflag
WHEN 1 THEN 'Active Employee'
ELSE 'Inactive Employee'
END AS [Salaried Flag]
FROM [AdventureWorks2019].[HumanResources].[employee]



Podemos especificar várias condições para a instrução CASE.
SELECT TOP 5 Nationalidnumber ,
CASE salariedflag
WHEN 1 THEN 'Active Employee'
WHEN 0 THEN 'Inactive Employee'
ELSE 'Invalid Value'
END AS [Salaried Flag]
FROM [AdventureWorks2019].[HumanResources].[employee]

Padronização de dados usando instruções SQL CASE


Normalmente, usamos abreviações para armazenar valores em tabelas SQL. As abreviaturas padrão são sexo, códigos de país, estado civil, nomes de produtos populares, etc.

Suponha que especificamos as abreviações para armazenar os gêneros dos funcionários. Agora, nosso aplicativo deve exibir os resultados sem abreviações.

As instruções SQL CASE ajudam a padronizar a saída para critérios definidos. Na consulta abaixo, usamos as seguintes condições:
  • Se o valor de gênero for M , exiba-o como Masculino
  • Se o valor de gênero for F , exiba-o como Feminino
  • Para quaisquer outros valores, exiba Inválido Valor
SELECT DISTINCT CASE gender
WHEN 'M' THEN 'Male'
WHEN 'F' THEN 'Female'
ELSE 'Invalid Value'
END AS Gender
FROM AdventureWorks2019.HumanResources.Employee


Declarações CASE pesquisadas


Na instrução CASE pesquisada, especificamos uma expressão CASE em vez dos valores diretos. Uma vez que o valor da expressão é avaliado e satisfaz uma condição na cláusula WHEN, seu valor correspondente é retornado.

Observe a consulta SQL abaixo. Aqui, definimos expressões na cláusula WHEN para [ListPrice]. Ele identifica que o custo do produto é $ 250 e está marcado como um item Eletrônico.
SELECT ProductNumber, Name, [Product category] = 
CASE 
WHEN ListPrice = 0 THEN 'Out of Stock items' 
WHEN ListPrice > 0 and ListPrice<=100 THEN 'Consumer goods' 
WHEN ListPrice >100 and ListPrice <= 500 THEN 'Electronics items' 
WHEN ListPrice >500 and ListPrice < 1500 THEN 'Luxury items' 
ELSE 'Extra items' 
END 
FROM Production.Product order by ListPrice desc

Para o exemplo de gênero mencionado anteriormente, podemos reescrever a instrução SQL CASE para as abreviações de gênero usando as instruções case pesquisadas.
SELECT DISTINCT CASE 
WHEN Gender='M' THEN 'Male'
WHEN Gender='F' THEN 'Female'
ELSE 'Invalid Value'
END AS Gender
FROM AdventureWorks2019.HumanResources.Employee


Usando instruções CASE com a cláusula ORDER BY


As consultas SQL usam a cláusula ORDER BY para classificação de dados em ordem crescente ou decrescente. Você pode usar as instruções CASE em conjunto com a cláusula ORDER BY. Suponha que da tabela de produtos, recuperamos o [ProductName] e o [ListPrice]. Queremos classificar os resultados das seguintes maneiras:
  • Se o preço de lista do produto for menor que 2.000, você deseja que o resultado seja na ordem de classificação padrão, ou seja, crescente
  • Se o preço da lista de produtos for maior que 2.000, a classificação da cláusula ORDER BY resultará em ordem decrescente

Nesta consulta, usamos duas instruções SQL CASE para implementar a lógica.
SELECT Name,
ListPrice
FROM Production.Product
ORDER BY CASE
WHEN ListPrice<=2000 THEN ListPrice END 
,CASE WHEN ListPrice >2000 THEN ListPrice END DESC



Na saída da consulta abaixo, você pode verificar as classificações de dados que aparecem em ordem crescente e decrescente.

Em outro exemplo, suponha que queremos classificar dados na tabela de funcionários com base na seguinte condição:
  • Para funcionários ativos (sinalizador atual =1), os dados devem classificar a coluna de data de contratação
  • Para funcionários inativos, deve classificar os dados de acordo com os valores na coluna data de nascimento
SELECT NationalIDNumber,JobTitle,Hiredate,BirthDate, currentflag
FROM AdventureWorks2019.HumanResources.Employee 
ORDER BY 
CASE CURRENTFLAG WHEN 1 THEN HireDate 
else Birthdate 
end

Na saída da consulta, podemos verificar a ordem de classificação de dados definida pela cláusula ORDER BY e instruções CASE.


Instrução CASE em SQL e funções agregadas


As funções agregadas no SQL Server realizam cálculos e retornam um único valor. Exemplos de funções agregadas são MIN, MAX, COUNT, ABG e CHECKSUM.

Suponha que queremos recuperar a contagem de contratação de funcionários para cada ano de 2007-2010. Ele deve exibir os resultados no seguinte formato:



Para isso, usamos a função agregada COUNT no SQL Server.
  • Primeiro, a função SQL DATEPART filtra os dados de acordo com o ano. Por exemplo, DATEPART(YY, Hiredate)=2007, filtra dados para o ano de 2007.
  • Em seguida, usamos a instrução CASE para retornar 1 se o ano for 2007.
  • A função de agregação de contagem conta os registros e exibe os resultados.
  • Da mesma forma, a consulta funciona para os anos restantes.
SELECT Count(CASE
WHEN Datepart(yy, hiredate) = 2007 THEN 1
ELSE NULL
END) AS [2007Hires],
Count(CASE
WHEN Datepart(yy, hiredate) = 2008 THEN 1
ELSE NULL
END) AS [2008Hires],
Count(CASE
WHEN Datepart(yy, hiredate) = 2009 THEN 1
ELSE NULL
END) AS [2009Hires],
Count(CASE
WHEN Datepart(yy, hiredate) = 2009 THEN 1
ELSE NULL
END) AS [2010Hires]
FROM AdventureWorks2019.HumanResources.Employee

Da mesma forma, digamos que queremos usar a função agregada GROUP BY para agrupar linhas com a mesma categoria de produto. Podemos especificar a instrução CASE em SQL para classificar dados do conjunto de resultados agrupados.
SELECT [Product category] = CASE
WHEN listprice = 0 THEN 'Out of Stock items'
WHEN listprice > 0
AND listprice <= 100 THEN 'Consumer goods'
WHEN listprice > 100
AND listprice <= 500 THEN 'Electronics items'
WHEN listprice > 500
AND listprice < 1500 THEN 'Luxury items'
ELSE 'Extra items'
END,
Min(listprice) AS MinPrice,
Max(listprice) AS MaxPrice,
Count(listprice) AS Numberofproducts
FROM production.product
GROUP BY CASE
WHEN listprice = 0 THEN 'Out of Stock items'
WHEN listprice > 0
AND listprice <= 100 THEN 'Consumer goods'
WHEN listprice > 100
AND listprice <= 500 THEN 'Electronics items'
WHEN listprice > 500
AND listprice < 1500 THEN 'Luxury items'
ELSE 'Extra items'
END
ORDER BY numberofproducts DESC

Na consulta acima, usamos duas instruções SQL CASE.
  • A primeira instrução CASE categoriza os dados com base na expressão definida no preço de tabela. Usando esta instrução CASE, dividimos os produtos nas seguintes categorias:
    • Itens esgotados
    • Bens de consumo
    • Itens eletrônicos
    • Itens de luxo
  • Na instrução do segundo caso, usamos a função agregada GROUP BY para agrupar o resultado por categoria
  • Além disso, classificamos os resultados de acordo com NumberOfProducts em ordem decrescente


Evite o erro de divisão por zero usando instruções SQL CASE


Um erro de divisão por zero ocorre se o valor do denominador for zero. Se você fizer essas frações no SQL Server, ele fornecerá o erro de divisão por zero, conforme mostrado abaixo.



É uma excelente prática escrever suas consultas de forma a evitar esses erros comuns. Para evitar isso, usamos a lógica de fração dentro de uma instrução CASE.
DECLARE @Student1 INT
DECLARE @Student2 INT

SET @Student1=100
SET @Student2=0

select
CASE WHEN @Student2=0
THEN NULL
ELSE @Student1/@Student2 end as StudentMarksRatio

Protegemos nossa consulta do erro de divisão por zero. Agora, com a lógica modificada, se obtivermos um zero no denominador, você obterá NULL na saída, conforme mostrado abaixo.


Lembretes úteis sobre a instrução SQL CASE

  • As instruções SQL CASE são compatíveis com até 10 níveis de aninhamento
  • Você não pode controlar o fluxo de execuções das instruções, funções ou procedimentos usando expressões CASE
  • Você deve sempre usar um bloco ELSE para que, se alguma condição não for satisfeita, você obtenha um valor padrão
  • Você deve evitar o uso de condições conflitantes na instrução SQL CASE. A instrução CASE funciona sequencialmente e para de avaliar com a primeira condição bem-sucedida