Een SQL CASE-instructie evalueert en retourneert resultaten op basis van bepaalde waarden, predikaten en voorwaarden volgens gedefinieerde logica. Stel dat u bijvoorbeeld een kiezerstabel heeft met de volgende details:
- Kiezer-ID
- Naam
- Geboorte
Als u op zoek was naar logica over het in aanmerking komen voor stemmen, zou dit afhankelijk zijn van de waarden in de DOB-kolom.
Als een kiezer ouder is dan 18 jaar, mag hij stemmen.
Laten we naar een ander voorbeeld kijken. Vaak slaan we de kolomwaarden op in bits 1 of 0. Stel dat u de waarden voor de beschikbaarheid van een product opslaat als 1 of 0. Bijvoorbeeld:
- 1 =Product is beschikbaar
- 0 =Product is niet op voorraad
Als we kijken naar het databaseperspectief, is het een goede gewoonte om waar mogelijk de afkortingen of bits te gebruiken. Het is nuttig voor de SQL Server-queryoptimalisatie bij het voorbereiden van het geoptimaliseerde uitvoeringsplan. Maar vanuit applicatieperspectief heeft de eindgebruiker deze waarden niet nodig. Klanten hoeven alleen maar te zien of het product beschikbaar is of niet.
In de onderstaande afbeelding zien we zowel het database- als het applicatieperspectief.
Wat doet de SQL CASE-instructie?
Een CASE-instructie in SQL Server evalueert een expressie en retourneert een waarde op basis van de gedefinieerde voorwaarden. Daarom werken in het eerdere voorbeeld de CASE-instructies zoals hieronder weergegeven.
Op hoog niveau wordt de syntaxis voor een SQL CASE-instructie hieronder weergegeven. Hier hebben we meerdere voorwaarden gespecificeerd. SQL Server evalueert de voorwaarden opeenvolgend. Zodra een voorwaarde met succes wordt geëvalueerd, stopt het de evaluatie van de resterende voorwaarden. Als aan geen van de voorwaarden is voldaan, kunnen we een optionele ELSE-instructie gebruiken om de standaardwaarde te retourneren. Als we bijvoorbeeld een andere waarde hebben dan 0 en 1 in de beschikbaarheidskolom, krijgt u de uitvoer van het ELSE-codeblok. Het vereist ten minste één set van de WHEN en THEN blokken. Het CASE-statement moet eindigen met het END-blok.
Laten we de SQL CASE-instructie onderzoeken aan de hand van verschillende voorbeelden.
Opmerking:in dit artikel gebruiken we de Microsoft-voorbeelddatabase AdventureWorks. U kunt de back-up downloaden van de Microsoft-documenten.
De SELECT-instructie met een eenvoudige CASE-uitdrukking
In dit type CASE-instructie gebruiken we gelijkheidscontrole-expressies. De volgende query implementeert een eenvoudige CASE-expressie.
- Als de waarde in de [SalariedFlag] 1 is, wordt de Actieve werknemer weergegeven
- Voor alle andere waarden wordt de uitvoer weergegeven als Inactieve werknemer
SELECT TOP 5 Nationalidnumber , CASE salariedflag WHEN 1 THEN 'Active Employee' ELSE 'Inactive Employee' END AS [Salaried Flag] FROM [AdventureWorks2019].[HumanResources].[employee]
We kunnen meerdere voorwaarden specificeren voor de CASE-instructie.
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]
Gegevensstandaardisatie met behulp van SQL CASE-statements
Meestal gebruiken we afkortingen om waarden op te slaan in SQL-tabellen. De standaardafkortingen zijn geslacht, landcodes, huwelijksstatus, populaire productnamen, enz.
Stel dat we de afkortingen specificeren voor het opslaan van de geslachten van werknemers. Nu zou onze applicatie de resultaten zonder afkortingen moeten weergeven.
SQL CASE-instructies helpen bij het standaardiseren van de uitvoer voor gedefinieerde criteria. In de onderstaande zoekopdracht gebruiken we de volgende voorwaarden:
- Als de geslachtswaarde M . is , geef het weer als Man
- Als de geslachtswaarde F . is , geef het weer als Vrouw
- Voor alle andere waarden geeft u Ongeldig . weer Waarde
SELECT DISTINCT CASE gender WHEN 'M' THEN 'Male' WHEN 'F' THEN 'Female' ELSE 'Invalid Value' END AS Gender FROM AdventureWorks2019.HumanResources.Employee
Gezochte CASE-statements
In de gezochte CASE-instructie geven we een CASE-expressie op in plaats van de directe waarden. Zodra de uitdrukkingswaarde een voorwaarde in de WHEN-component evalueert en voldoet, wordt de bijbehorende waarde geretourneerd.
Bekijk de onderstaande SQL-query. Hier hebben we expressies gedefinieerd in de WHEN-component voor de [ListPrice]. Het geeft aan dat de productprijs $ 250 is en is gemarkeerd als een elektronica-item.
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
Voor het eerder genoemde gendervoorbeeld kunnen we de SQL CASE-instructie voor de geslachtsafkortingen herschrijven met behulp van de gezochte case-statements.
SELECT DISTINCT CASE WHEN Gender='M' THEN 'Male' WHEN Gender='F' THEN 'Female' ELSE 'Invalid Value' END AS Gender FROM AdventureWorks2019.HumanResources.Employee
CASE-statements gebruiken met de ORDER BY-clausule
SQL-query's gebruiken de ORDER BY-component voor het sorteren van gegevens in oplopende of aflopende volgorde. U kunt de CASE-instructies gebruiken in combinatie met de ORDER BY-clausule. Stel dat we uit de tabel met producten de [ProductName] en [ListPrice] ophalen. We willen de resultaten op de volgende manieren sorteren:
- Als de productcatalogusprijs lager is dan 2000, wilt u dat het resultaat in de standaardsorteervolgorde staat, d.w.z. oplopend
- Als de productcatalogusprijs hoger is dan 2.000, resulteert de ORDER BY-clausule in aflopende volgorde
In deze query gebruiken we twee SQL CASE-statements om de logica te implementeren.
SELECT Name, ListPrice FROM Production.Product ORDER BY CASE WHEN ListPrice<=2000 THEN ListPrice END ,CASE WHEN ListPrice >2000 THEN ListPrice END DESC
In de onderstaande query-uitvoer kunt u controleren of de gegevenssortering zowel in aflopende als oplopende volgorde wordt weergegeven.
Stel in een ander voorbeeld dat we gegevens in de werknemerstabel willen sorteren op basis van de volgende voorwaarde:
- Voor actieve werknemers (huidige vlag =1) moeten de gegevens in de kolom voor de aanstellingsdatum worden gesorteerd
- Voor inactieve werknemers moet het gegevens sorteren volgens de waarden in de geboortedatumkolom
SELECT NationalIDNumber,JobTitle,Hiredate,BirthDate, currentflag FROM AdventureWorks2019.HumanResources.Employee ORDER BY CASE CURRENTFLAG WHEN 1 THEN HireDate else Birthdate end
In de uitvoer van de query kunnen we de sorteervolgorde van gegevens verifiëren die is gedefinieerd door de ORDER BY-clausule en CASE-instructies.
CASE-instructie in SQL en aggregatiefuncties
Geaggregeerde functies in SQL Server voeren berekeningen uit en retourneren een enkele waarde. Voorbeelden van aggregatiefuncties zijn MIN, MAX, COUNT, ABG en CHECKSUM.
Stel dat we voor elk jaar van 2007-2010 het aantal werknemers in dienst willen nemen. Het zou de resultaten in het volgende formaat moeten weergeven:
Voor dit doel gebruiken we de COUNT-aggregatiefunctie in SQL Server.
- Ten eerste filtert de SQL DATEPART-functie gegevens op jaar. De DATEPART(YY, Hiredate)=2007 filtert bijvoorbeeld gegevens voor het jaar 2007.
- We gebruiken dan de CASE-instructie om 1 te retourneren als het jaar 2007 is.
- De telfunctie telt de records en geeft de resultaten weer.
- Op dezelfde manier werkt de zoekopdracht voor de resterende jaren.
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
Evenzo, laten we zeggen dat we de aggregatiefunctie GROUP BY willen gebruiken om rijen met dezelfde productcategorie te groeperen. We kunnen de CASE-instructie in SQL specificeren om gegevens uit de gegroepeerde resultatenset te sorteren.
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
In de bovenstaande query gebruiken we twee SQL CASE-statements.
- De eerste CASE-instructie categoriseert de gegevens op basis van de uitdrukking die is gedefinieerd in de catalogusprijs. Met behulp van deze CASE-verklaring verdelen we de producten in de volgende categorieën:
- Niet op voorraad artikelen
- Consumentengoederen
- Elektronische artikelen
- Luxe items
- In de tweede case-statement gebruiken we de GROUP BY-aggregatiefunctie om het resultaat te groeperen op categorie
- Verder sorteren we de resultaten volgens het aantal producten in aflopende volgorde
Voorkom fouten bij delen door nul met SQL CASE-statements
Een deling door nul-fout treedt op als de noemerwaarde nul is. Als u deze breuken in SQL Server doet, krijgt u de fout door nul te delen, zoals hieronder weergegeven.
Het is een uitstekende gewoonte om uw vragen zo te schrijven dat deze veelvoorkomende fouten worden voorkomen. Om dit te voorkomen, gebruiken we de breuklogica in een CASE-statement.
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
We hebben onze query gevrijwaard van de fout door delen door nul. Nu, met de gewijzigde logica, als we een nul in de noemer krijgen, krijg je NULL in de uitvoer zoals hieronder weergegeven.
Nuttige herinneringen over de SQL CASE-instructie
- SQL CASE-statements ondersteunen tot 10 niveaus van nesting
- U kunt de stroom van uitvoeringen van de instructies, functies of procedures niet controleren met behulp van CASE-expressies
- Je moet altijd een ELSE-blok gebruiken, zodat je een standaardwaarde krijgt als aan een van de voorwaarden niet wordt voldaan
- U moet het gebruik van conflicterende voorwaarden in de SQL CASE-instructie vermijden. De CASE-instructie werkt sequentieel en stopt met evalueren bij de eerste succesvolle voorwaarde