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

Sentencia SQL CASE:¿Qué es y cuáles son las mejores formas de usarla?

Una declaración SQL CASE evalúa y devuelve resultados basados ​​en valores, predicados y condiciones particulares según la lógica definida. Por ejemplo, suponga que tiene una tabla de votantes con los siguientes detalles:

  • Identificación de votante
  • Nombre
  • Fecha de nacimiento

Si estuviera buscando lógica sobre la elegibilidad para votar, esto dependería de los valores en la columna DOB.

Si la edad de un votante es mayor de 18 años, es elegible para votar.

Veamos otro ejemplo. Muchas veces, almacenamos los valores de las columnas en los bits 1 o 0. Supongamos que almacena los valores de disponibilidad de un producto como 1 o 0. Por ejemplo:

  • 1 =El producto está disponible
  • 0 =El producto está agotado

Si miramos la perspectiva de la base de datos, es una buena práctica usar las abreviaturas o bits siempre que sea posible. Es beneficioso para el optimizador de consultas de SQL Server en la preparación del plan de ejecución optimizado. Pero, desde la perspectiva de la aplicación, el usuario final no requiere estos valores. Los clientes solo necesitan ver si el producto está disponible o no.

En la siguiente imagen, vemos la perspectiva de la base de datos y la aplicación.

¿Qué hace la sentencia SQL CASE?

Una declaración CASE en SQL Server evalúa una expresión y devuelve un valor basado en las condiciones definidas. Por lo tanto, en el ejemplo anterior, las instrucciones CASE funcionan como se muestra a continuación.

En un nivel alto, la sintaxis de una instrucción SQL CASE se muestra a continuación. Aquí, especificamos múltiples condiciones. SQL Server evalúa las condiciones secuencialmente. Una vez que una condición se evalúa con éxito, detiene la evaluación de las condiciones restantes. Si no se cumple ninguna de las condiciones, podemos usar una instrucción ELSE opcional para devolver el valor predeterminado. Por ejemplo, si tenemos un valor diferente a 0 y 1 en la columna de disponibilidad, obtienes el resultado del bloque de código ELSE. Requiere al menos un conjunto de bloques CUANDO y ENTONCES. La instrucción CASE debe terminar con el bloque END.

Exploremos la declaración SQL CASE usando varios ejemplos.

Nota:En este artículo, usamos la base de datos de muestra de Microsoft, AdventureWorks. Puede descargar su copia de seguridad desde Microsoft Docs.

La declaración SELECT con una expresión CASE simple

En este tipo de declaración CASE, usamos expresiones de verificación de igualdad. La siguiente consulta implementa una expresión CASE simple.

  • Si el valor en [SalariedFlag] es 1, entonces muestra el Empleado activo
  • Para todos los demás valores, muestra el resultado como Empleado inactivo
SELECT TOP 5 Nationalidnumber ,
CASE salariedflag
WHEN 1 THEN 'Active Employee'
ELSE 'Inactive Employee'
END AS [Salaried Flag]
FROM [AdventureWorks2019].[HumanResources].[employee]

Podemos especificar múltiples condiciones para la instrucción 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]

Estandarización de datos usando sentencias SQL CASE

Por lo general, usamos abreviaturas para almacenar valores en tablas SQL. Las abreviaturas estándar son género, códigos de país, estado civil, nombres de productos populares, etc.

Supongamos que especificamos las abreviaturas para almacenar los géneros de los empleados. Ahora, nuestra aplicación debería mostrar los resultados sin abreviaturas.

Las sentencias SQL CASE ayudan a estandarizar la salida para criterios definidos. En la siguiente consulta, usamos las siguientes condiciones:

  • Si el valor de sexo es M , mostrarlo como Masculino
  • Si el valor de sexo es F , mostrarlo como Mujer
  • Para cualquier otro valor, mostrar No válido Valor
SELECT DISTINCT CASE gender
WHEN 'M' THEN 'Male'
WHEN 'F' THEN 'Female'
ELSE 'Invalid Value'
END AS Gender
FROM AdventureWorks2019.HumanResources.Employee

Declaraciones CASE buscadas

En la instrucción CASE buscada, especificamos una expresión CASE en lugar de los valores directos. Una vez que el valor de la expresión evalúa y satisface una condición en la cláusula WHEN, se devuelve su valor correspondiente.

Mire la siguiente consulta SQL. Aquí, definimos expresiones en la cláusula WHEN para [ListPrice]. Identifica que el costo del producto es de $250 y está marcado como un artículo de Electrónica.

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 el ejemplo de género mencionado anteriormente, podemos reescribir la declaración SQL CASE para las abreviaturas de género utilizando las declaraciones de caso buscadas.

SELECT DISTINCT CASE 
WHEN Gender='M' THEN 'Male'
WHEN Gender='F' THEN 'Female'
ELSE 'Invalid Value'
END AS Gender
FROM AdventureWorks2019.HumanResources.Employee

Uso de sentencias CASE con la cláusula ORDER BY

Las consultas SQL utilizan la cláusula ORDER BY para clasificar los datos en orden ascendente o descendente. Puede utilizar las sentencias CASE junto con la cláusula ORDER BY. Supongamos que de la tabla de productos recuperamos [ProductName] y [ListPrice]. Queremos ordenar los resultados de las siguientes maneras:

  • Si el precio de lista del producto es inferior a 2000, desea que el resultado se encuentre en el orden de clasificación predeterminado, es decir, ascendente
  • Si el precio de lista del producto es superior a 2000, la clasificación de la cláusula ORDER BY da como resultado un orden descendente

En esta consulta, usamos dos sentencias SQL CASE para implementar la 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

En el resultado de la consulta a continuación, puede verificar los tipos de datos que aparecen en orden ascendente y descendente.

En otro ejemplo, supongamos que queremos ordenar los datos en la tabla de empleados según la siguiente condición:

  • Para los empleados activos (marca actual =1), los datos deben ordenar la columna de fecha de contratación
  • Para los empleados inactivos, debe ordenar los datos según los valores en la columna de fecha de nacimiento
SELECT NationalIDNumber,JobTitle,Hiredate,BirthDate, currentflag
FROM AdventureWorks2019.HumanResources.Employee 
ORDER BY 
CASE CURRENTFLAG WHEN 1 THEN HireDate 
else Birthdate 
end

En el resultado de la consulta, podemos verificar el orden de clasificación de datos definido por la cláusula ORDER BY y las declaraciones CASE.

Declaración CASE en SQL y funciones agregadas

Las funciones agregadas en SQL Server realizan cálculos y devuelven un solo valor. Ejemplos de funciones agregadas son MIN, MAX, COUNT, ABG y CHECKSUM.

Supongamos que queremos recuperar el recuento de empleados contratados para cada año desde 2007-2010. Debería mostrar los resultados en el siguiente formato:

Para este propósito, usamos la función agregada COUNT en SQL Server.

  • Primero, la función SQL DATEPART filtra los datos según el año. Por ejemplo, DATEPART(YY, Hiredate)=2007, filtra datos para el año 2007.
  • Luego usamos la instrucción CASE para devolver 1 si el año es 2007.
  • La función de conteo agregado cuenta los registros y muestra los resultados.
  • Del mismo modo, la consulta funciona para los años 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

De manera similar, digamos que queremos usar la función agregada GROUP BY para agrupar filas que tienen la misma categoría de producto. Podemos especificar la instrucción CASE en SQL para ordenar los datos del 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

En la consulta anterior, usamos dos sentencias SQL CASE.

  • La primera instrucción CASE clasifica los datos en función de la expresión definida en el precio de lista. Utilizando esta instrucción CASE, dividimos los productos en las siguientes categorías:
    • Artículos agotados
    • Bienes de consumo
    • Artículos electrónicos
    • Artículos de lujo
  • En la declaración del segundo caso, usamos la función agregada GROUP BY para agrupar el resultado por categoría
  • Además, ordenamos los resultados según el Número de productos en orden descendente

Evite el error de división por cero usando sentencias SQL CASE

Se produce un error de división por cero si el valor del denominador es cero. Si hace estas fracciones en SQL Server, obtendrá el error de dividir por cero como se muestra a continuación.

Es una excelente práctica escribir sus consultas de manera de evitar estos errores comunes. Para evitar esto, usamos la lógica de fracciones dentro de una instrucción 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

Hemos salvaguardado nuestra consulta del error de dividir por cero. Ahora, con la lógica modificada, si obtenemos un cero en el denominador, obtendrá NULL en la salida como se muestra a continuación.

Recordatorios útiles sobre la instrucción SQL CASE

  • Las sentencias SQL CASE admiten hasta 10 niveles de anidamiento
  • No puede controlar el flujo de ejecuciones de declaraciones, funciones o procedimientos usando expresiones CASE
  • Siempre debe usar un bloque ELSE para que, si alguna condición no se cumple, obtenga un valor predeterminado
  • Debe evitar el uso de condiciones conflictivas en la instrucción SQL CASE. La declaración CASE funciona secuencialmente y deja de evaluar con la primera condición exitosa