sql >> Database >  >> RDS >> Sqlserver

SQL CASE-instructie:wat is het en wat zijn de beste manieren om het te gebruiken?

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

  1. Is er een manier om OracleCommand.BindByName te dwingen standaard waar te zijn voor ODP.NET?

  2. Recursie in Oracle

  3. MySQL UPDATE en SELECT in één keer

  4. 3 manieren om alle opgeslagen procedures in een SQL Server-database op te sommen