Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Instruction SQL CASE :qu'est-ce que c'est et quelles sont les meilleures façons de l'utiliser ?

Une instruction SQL CASE évalue et renvoie des résultats en fonction de valeurs, de prédicats et de conditions particuliers conformément à la logique définie. Par exemple, supposons que vous ayez une table des électeurs avec les détails suivants :

  • Identifiant de l'électeur
  • Nom
  • DOB

Si vous recherchiez une logique concernant l'éligibilité au vote, cela dépendrait des valeurs de la colonne DOB.

Si l'âge d'un électeur est supérieur à 18 ans, il a le droit de voter.

Prenons un autre exemple. Souvent, nous stockons les valeurs des colonnes en bits 1 ou 0. Supposons que vous stockiez les valeurs de disponibilité d'un produit sous la forme 1 ou 0. Par exemple :

  • 1 =Le produit est disponible
  • 0 =Le produit est en rupture de stock

Du point de vue de la base de données, il est recommandé d'utiliser les abréviations ou les bits dans la mesure du possible. Il est avantageux pour l'optimiseur de requête SQL Server de préparer le plan d'exécution optimisé. Mais, du point de vue de l'application, l'utilisateur final n'a pas besoin de ces valeurs. Les clients n'ont qu'à voir si le produit est disponible ou non.

Dans l'image ci-dessous, nous voyons à la fois la perspective de la base de données et celle de l'application.

Que fait l'instruction SQL CASE ?

Une instruction CASE dans SQL Server évalue une expression et renvoie une valeur basée sur les conditions définies. Par conséquent, dans l'exemple précédent, les instructions CASE fonctionnent comme indiqué ci-dessous.

À un niveau élevé, la syntaxe d'une instruction SQL CASE est illustrée ci-dessous. Ici, nous avons spécifié plusieurs conditions. SQL Server évalue les conditions de manière séquentielle. Une fois qu'une condition est évaluée avec succès, elle arrête l'évaluation des conditions restantes. Si aucune des conditions n'est satisfaite, nous pouvons utiliser une instruction facultative ELSE pour renvoyer la valeur par défaut. Par exemple, si nous avons une valeur différente de 0 et 1 dans la colonne de disponibilité, vous obtenez la sortie du bloc de code ELSE. Il nécessite au moins un ensemble de blocs WHEN et THEN. L'instruction CASE doit se terminer par le bloc END.

Explorons l'instruction SQL CASE à l'aide de divers exemples.

Remarque :dans cet article, nous utilisons l'exemple de base de données Microsoft, AdventureWorks. Vous pouvez télécharger sa sauvegarde à partir de Microsoft Docs.

L'instruction SELECT avec une simple expression CASE

Dans ce type d'instruction CASE, nous utilisons des expressions de contrôle d'égalité. La requête suivante implémente une expression CASE simple.

  • Si la valeur dans le [SalariedFlag] est 1, alors il affiche l' employé actif
  • Pour toutes les autres valeurs, il affiche la sortie comme Employé inactif
SELECT TOP 5 Nationalidnumber ,
CASE salariedflag
WHEN 1 THEN 'Active Employee'
ELSE 'Inactive Employee'
END AS [Salaried Flag]
FROM [AdventureWorks2019].[HumanResources].[employee]

Nous pouvons spécifier plusieurs conditions pour l'instruction 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]

Standardisation des données à l'aide d'instructions SQL CASE

Habituellement, nous utilisons des abréviations pour stocker des valeurs dans des tables SQL. Les abréviations standard sont le sexe, les codes de pays, le statut matrimonial, les noms de produits populaires, etc.

Supposons que nous spécifions les abréviations pour stocker les sexes des employés. Maintenant, notre application devrait afficher les résultats sans aucune abréviation.

Les instructions SQL CASE aident à normaliser la sortie pour des critères définis. Dans la requête ci-dessous, nous utilisons les conditions suivantes :

  • Si la valeur de sexe est M , affichez-le comme Masculin
  • Si la valeur de sexe est F , affichez-le comme Femme
  • Pour toute autre valeur, affichez Non valide Valeur
SELECT DISTINCT CASE gender
WHEN 'M' THEN 'Male'
WHEN 'F' THEN 'Female'
ELSE 'Invalid Value'
END AS Gender
FROM AdventureWorks2019.HumanResources.Employee

Déclarations CASE recherchées

Dans l'instruction CASE recherchée, nous spécifions une expression CASE au lieu des valeurs directes. Une fois que la valeur de l'expression est évaluée et satisfait une condition dans la clause WHEN, sa valeur correspondante est renvoyée.

Regardez la requête SQL ci-dessous. Ici, nous avons défini des expressions dans la clause WHEN pour le [ListPrice]. Il identifie que le coût du produit est de 250 $ et est marqué comme un article électronique.

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

Pour l'exemple de genre mentionné précédemment, nous pouvons réécrire l'instruction SQL CASE pour les abréviations de genre en utilisant les instructions de cas recherchées.

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

Utilisation des instructions CASE avec la clause ORDER BY

Les requêtes SQL utilisent la clause ORDER BY pour trier les données dans l'ordre croissant ou décroissant. Vous pouvez utiliser les instructions CASE conjointement avec la clause ORDER BY. Supposons que dans la table des produits, nous récupérons le [ProductName] et le [ListPrice]. Nous souhaitons trier les résultats de la manière suivante :

  • Si le prix catalogue du produit est inférieur à 2 000, vous souhaitez que le résultat soit dans l'ordre de tri par défaut, c'est-à-dire par ordre croissant
  • Si le prix catalogue du produit est supérieur à 2 000, le tri de la clause ORDER BY donne l'ordre décroissant

Dans cette requête, nous utilisons deux instructions SQL CASE pour implémenter la logique.

SELECT Name,
ListPrice
FROM Production.Product
ORDER BY CASE
WHEN ListPrice<=2000 THEN ListPrice END 
,CASE WHEN ListPrice >2000 THEN ListPrice END DESC

Dans la sortie de requête ci-dessous, vous pouvez vérifier les tris de données apparaissant dans l'ordre décroissant et croissant.

Dans un autre exemple, supposons que nous voulions trier les données de la table des employés en fonction de la condition suivante :

  • Pour les employés actifs (Indicateur actuel = 1), les données doivent trier la colonne de date d'embauche
  • Pour les employés inactifs, il doit trier les données en fonction des valeurs de la colonne de date de naissance
SELECT NationalIDNumber,JobTitle,Hiredate,BirthDate, currentflag
FROM AdventureWorks2019.HumanResources.Employee 
ORDER BY 
CASE CURRENTFLAG WHEN 1 THEN HireDate 
else Birthdate 
end

Dans la sortie de la requête, nous pouvons vérifier l'ordre de tri des données défini par la clause ORDER BY et les instructions CASE.

Instruction CASE en SQL et fonctions d'agrégation

Les fonctions d'agrégation dans SQL Server effectuent des calculs et renvoient une valeur unique. Des exemples de fonctions d'agrégation sont MIN, MAX, COUNT, ABG et CHECKSUM.

Supposons que nous voulions récupérer le nombre d'embauches d'employés pour chaque année de 2007 à 2010. Il doit afficher les résultats au format suivant :

À cette fin, nous utilisons la fonction d'agrégation COUNT dans SQL Server.

  • Tout d'abord, la fonction SQL DATEPART filtre les données en fonction de l'année. Par exemple, DATEPART(YY, Hiredate)=2007, filtre les données pour l'année 2007.
  • Nous utilisons ensuite l'instruction CASE pour renvoyer 1 si l'année est 2007.
  • La fonction d'agrégation count compte les enregistrements et affiche les résultats.
  • De même, la requête fonctionne pour les années 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 même, disons que nous voulons utiliser la fonction d'agrégation GROUP BY pour regrouper les lignes ayant la même catégorie de produits. Nous pouvons spécifier l'instruction CASE en SQL pour trier les données du jeu de résultats groupé.

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

Dans la requête ci-dessus, nous utilisons deux instructions SQL CASE.

  • La première instruction CASE catégorise les données en fonction de l'expression définie dans le prix catalogue. À l'aide de cette déclaration CASE, nous divisons les produits dans les catégories suivantes :
    • Articles en rupture de stock
    • Biens de consommation
    • Articles électroniques
    • Articles de luxe
  • Dans la deuxième instruction case, nous utilisons la fonction d'agrégation GROUP BY pour regrouper le résultat par catégorie
  • De plus, nous trions les résultats selon le NumberOfProducts dans l'ordre décroissant

Éviter les erreurs de division par zéro à l'aide des instructions SQL CASE

Une erreur de division par zéro se produit si la valeur du dénominateur est zéro. Si vous faites ces fractions dans SQL Server, cela vous donnera l'erreur de division par zéro comme indiqué ci-dessous.

C'est une excellente pratique de rédiger vos requêtes de manière à éviter ces erreurs courantes. Pour éviter cela, nous utilisons la logique des fractions dans une instruction 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

Nous avons protégé notre requête contre l'erreur de division par zéro. Maintenant, avec la logique modifiée, si nous obtenons un zéro au dénominateur, vous obtenez NULL dans la sortie comme indiqué ci-dessous.

Rappels utiles sur l'instruction SQL CASE

  • Les instructions SQL CASE prennent en charge jusqu'à 10 niveaux d'imbrication
  • Vous ne pouvez pas contrôler le flux d'exécution des instructions, fonctions ou procédures à l'aide d'expressions CASE
  • Vous devez toujours utiliser un bloc ELSE afin que si des conditions ne sont pas satisfaites, vous obteniez une valeur par défaut
  • Vous devez éviter d'utiliser des conditions conflictuelles dans l'instruction SQL CASE. L'instruction CASE fonctionne de manière séquentielle et arrête l'évaluation avec la première condition réussie