sql >> Database >  >> RDS >> Sqlserver

CASE-expressies gebruiken in SQL Server

Inleiding

CASE-expressies in SQL Server worden gebruikt voor de vervanging van kolomwaarden om de resultatensets op een bepaalde manier of eenvoudige query's weer te geven. Er zijn verschillende toepassingen voor dergelijke commando's.

Er is bijvoorbeeld een kolom met de afdelingscode, maar u wilt de naam van de afdeling weergeven in plaats van de code. Je zou dit kunnen bereiken door een JOIN te doen met een andere tabel die de afdelingsdetails bevat. Laten we er echter van uitgaan dat u de zoekopdracht relatief eenvoudig wilt houden. Een ander gebruiksscenario is het retourneren van specifieke waarden voor de set berekende waarden. Berekende kolommen zouden niet passen als de sets voorwaarden die moeten worden gespecificeerd niet hetzelfde zijn.

Doorgaans heeft de SQL Server CASE-expressies de vorm die wordt weergegeven in Listing 1.

-- Listing 1: CASE Expression Syntax
-- Simple CASE Expression
SELECT 
  col1
, col2
, CASE col3
WHEN 'a' THEN 'xxx'
WHEN 'b' THEN 'yyy'
WHEN 'c' THEN 'zzz'
ELSE 'Invalid Value'
END AS col3_name
FROM table_name;

-- Searched CASE Expression
SELECT 
  col1
, col2
, CASE
WHEN col3 = 1 THEN 'xxx'
WHEN col3 BETWEEN 2 and 9 THEN 'yyy'
WHEN col3 > 10 THEN 'zzz'
ELSE 'Invalid Value'
END AS col3_name
FROM table_name;

Eenvoudige casus en gezochte casus

De twee hierboven beschreven scenario's passen redelijk goed in de twee typen CASE-expressies die beschikbaar zijn in SQL Server. Een eenvoudige CASE-expressie laat alleen gelijkheidscontroles toe. Een gezochte CASE-expressie staat zelfs Booleaanse expressies toe.

Merk op dat de resultaten van een CASE-expressie in één kolom passen. Merk ook op dat we de kolomnaam specificeren net na de CASE-clausule in de Simple CASE-expressie. In de Searched CASE Expression moeten we echter de kolomnaam voor elke Booleaanse expressie specificeren. Laten we enkele voorbeelden bekijken.

Scenario-omgeving

Bij onze verkenning van de CASE-expressie zullen we de bekende WideWorldImporters-voorbeelddatabase gebruiken. Daar gebruiken we de Sales.CustomerTransactions tabel om verschillende scenario's van de toepassing CASE-expressie te demonstreren. Zoals gebruikelijk is bij T-SQL, is het mogelijk om vergelijkbare resultaten te krijgen met behulp van andere technieken, zoals JOIN's, maar we concentreren ons op één tabel om de CASE-expressiemogelijkheden te tonen.

Merk op dat men de verwerkte gegevens moet begrijpen om CASE-expressies te kunnen gebruiken. We moeten bijvoorbeeld weten wat elke klant code betekent om de gegevens met meer betekenis voor de eindgebruiker weer te geven. In onze gevallen kunnen we de informatie uit andere tabellen halen.

Listing 2 is een eenvoudige query die laat zien hoe de gegevens in de tabel eruit zien. Afbeelding 1 toont ons een uitvoergedeelte.

-- Listing 2: Data Set in Sales.CustomerTransactions
SELECT TOP (1000) [CustomerTransactionID]
      , [CustomerID]
      , [TransactionTypeID]
      , [InvoiceID]
      , [PaymentMethodID]
      , [TransactionDate]
      , [AmountExcludingTax]
      , [TaxAmount]
      , [TransactionAmount]
      , [OutstandingBalance]
      , [FinalizationDate]
      , [IsFinalized]
      , [LastEditedBy]
      , [LastEditedWhen]
  FROM [WideWorldImporters].[Sales].[CustomerTransactions] ;

Klantnamen retourneren op basis van klant-ID

In dit voorbeeld willen we de naam van elke klant weergeven op basis van de klantcode. We halen de namen van klanten uit een andere tabel met behulp van een JOIN-query. Nogmaals, we gebruiken de CASE Expression om te demonstreren wat deze aanpak kan doen.

-- Listing 3a: Determine Names Using a Join
select distinct top 10 b.CustomerID, a.CustomerName
from Sales.Customers a,Sales.CustomerTransactions b
where a.CustomerID = b.CustomerID;
-- Listing 3b: Determine Names Using a Join (Alternative)
select distinct top 10 b.CustomerID, a.CustomerName
from Sales.Customers a
inner join Sales.CustomerTransactions b
on a.CustomerID = b.CustomerID;

Met deze informatie schrijven we een eenvoudige CASE-query om alleen gegevens van Sales.CustomerTransactions op te halen (zie lijst 4). Afbeelding 3 markeert de namen die door de zoekopdracht zijn geretourneerd.

Let op het voorkomen van 'Onbekende klanten' in de uitvoer. In de echte zin zijn deze klanten niet onbekend. We hebben ze niet omdat we niet rekening hebben gehouden met hun klant-ID in onze CASE-uitdrukking. Dit ondersteunt de noodzaak om de gegevens te begrijpen bij het gebruik van CASE Expressions.

-- Listing 4: Simple CASE Expression for Customer Name
SELECT TOP (20) 
CASE CustomerID 
	WHEN 1 THEN 'Tailspin Toys'
	WHEN 401 THEN 'Wingtip Toys'
	WHEN 801 THEN 'Eric Torres'
	WHEN 802 THEN 'Cosmina Vlad'
	WHEN 803 THEN 'Bala Dixit'
	WHEN 804 THEN 'Alekxandrs Reikstins'
	WHEN 805 THEN 'Ratan Podder'
	WHEN 806 THEN 'Shi Tu'
	WHEN 807 THEN 'Gunnar Lohmus'
	WHEN 808 THEN 'Jackson Kolios'
ELSE 'Unknown Customer'
END CustomerName
      , [InvoiceID]
      , [TransactionDate]
      , [TransactionAmount]
      , [OutstandingBalance]
      , [IsFinalized]
	  , [FinalizationDate]
      , [LastEditedBy]
      , [LastEditedWhen]
  FROM [WideWorldImporters].[Sales].[CustomerTransactions];

De klantklasse teruggeven op basis van het transactiebedrag

In dit voorbeeld gebruiken we de Searched CASE-expressie om te laten zien welke van onze klanten van meer waarde is met betrekking tot de transactiewaarde.

We classificeren de klanten in drie groepen - Normaal, Zilver, Goud en Platina, op basis van de transactiewaarde. Dit is natuurlijk simplistisch. In een realistisch scenario zouden we hun transacties over een bepaalde periode moeten optellen. In dit geval gebruiken we alleen een gegevenssubset om de CASE Expression-mogelijkheden te tonen.

-- Listing 5: Searched Case Expression for Customer Class 
SELECT TOP (20) 
CASE CustomerID 
	WHEN 1 THEN 'Tailspin Toys'
	WHEN 401 THEN 'Wingtip Toys'
	WHEN 801 THEN 'Eric Torres'
	WHEN 802 THEN 'Cosmina Vlad'
	WHEN 803 THEN 'Bala Dixit'
	WHEN 804 THEN 'Alekxandrs Reikstins'
	WHEN 805 THEN 'Ratan Podder'
	WHEN 806 THEN 'Shi Tu'
	WHEN 807 THEN 'Gunnar Lohmus'
	WHEN 808 THEN 'Jackson Kolios'
ELSE 'Unknown Customer'
END CustomerName
      	, [InvoiceID]
	, [TransactionDate] 
, CASE  
	WHEN [TransactionAmount] BETWEEN 100 AND 1000 THEN 'Silver Customer'
	WHEN [TransactionAmount] BETWEEN 1000 AND 3000 THEN 'Gold Customer'
	WHEN [TransactionAmount] >= 3000 THEN 'Platinum Customer'
	ELSE 'Regular Customer'
	END AS CustomerClass
, [OutstandingBalance]
      	, [IsFinalized]
	  , [FinalizationDate]
      	, [LastEditedBy]
      	, [LastEditedWhen]
  FROM [WideWorldImporters].[Sales].[CustomerTransactions];

De dag van de week teruggeven met geneste CASE-expressies

We gaan verder met de monsters door een monster toe te voegen dat ons vertelt op welke dag van de week de transactiedatum was (zie aanbieding 6). Merk op dat we dit hadden kunnen bereiken door een veel eenvoudigere vorm van de query te gebruiken met de functie DATENAME in plaats van de functie DATEPART.

-- Listing 6: Case Expression for Day of Week Using A Function  
SELECT TOP (20) 
CASE CustomerID 
	WHEN 1 THEN 'Tailspin Toys'
	WHEN 401 THEN 'Wingtip Toys'
	WHEN 801 THEN 'Eric Torres'
	WHEN 802 THEN 'Cosmina Vlad'
	WHEN 803 THEN 'Bala Dixit'
	WHEN 804 THEN 'Alekxandrs Reikstins'
	WHEN 805 THEN 'Ratan Podder'
	WHEN 806 THEN 'Shi Tu'
	WHEN 807 THEN 'Gunnar Lohmus'
	WHEN 808 THEN 'Jackson Kolios'
ELSE 'Unknown Customer'
END CustomerName
      , [InvoiceID]
, CASE  
	WHEN DATEPART(WEEKDAY,[TransactionDate]) = 1 THEN 'Sunday'
	WHEN DATEPART(WEEKDAY,[TransactionDate]) = 2 THEN 'Monday'
	WHEN DATEPART(WEEKDAY,[TransactionDate]) = 3 THEN 'Tuesday'
	WHEN DATEPART(WEEKDAY,[TransactionDate]) = 4 THEN 'Wednesday'
	WHEN DATEPART(WEEKDAY,[TransactionDate]) = 5 THEN 'Thursday'
	WHEN DATEPART(WEEKDAY,[TransactionDate]) = 6 THEN 'Friday'
	WHEN DATEPART(WEEKDAY,[TransactionDate]) = 7 THEN 'Saturday'
	END AS [Day of Week]
, CASE  
	WHEN [TransactionAmount] BETWEEN 100 AND 1000 THEN 'Silver Customer'
	WHEN [TransactionAmount] BETWEEN 1000 AND 3000 THEN 'Gold Customer'
	WHEN [TransactionAmount] >= 3000 THEN 'Platinum Customer'
	ELSE 'Regular Customer'
	END AS CustomerClass
	  , [OutstandingBalance]
      , [IsFinalized]
	  , [FinalizationDate]
      , [LastEditedBy]
      , [LastEditedWhen]
  FROM [WideWorldImporters].[Sales].[CustomerTransactions];

Transacties labelen op basis van datum

Met behulp van de code in listings 7 en 8 kunnen we transacties labelen op basis van het verschil tussen de huidige datum en de transactiedatum. Dit geldt ook voor het verschil tussen de transactiedatum en een andere kolom. Daarom kunnen we andere kolommen introduceren dan waarmee we werken als invoer voor een Booleaanse uitdrukking.

  -- Listing 7: Case Expression for Transaction by Comparing Two “Columns”
SELECT TOP (20) 
CASE CustomerID 
	WHEN 1 THEN 'Tailspin Toys'
	WHEN 401 THEN 'Wingtip Toys'
	WHEN 801 THEN 'Eric Torres'
	WHEN 802 THEN 'Cosmina Vlad'
	WHEN 803 THEN 'Bala Dixit'
	WHEN 804 THEN 'Alekxandrs Reikstins'
	WHEN 805 THEN 'Ratan Podder'
	WHEN 806 THEN 'Shi Tu'
	WHEN 807 THEN 'Gunnar Lohmus'
	WHEN 808 THEN 'Jackson Kolios'
ELSE 'Unknown Customer'
END CustomerName
      , [InvoiceID]
, CASE  
	WHEN DATEDIFF(DAY,[TransactionDate],GETDATE()) < 30 THEN 'Current Transaction'
	WHEN DATEDIFF(DAY,[TransactionDate],GETDATE()) BETWEEN 30 AND 90 THEN 'Old Transaction'
	WHEN DATEDIFF(DAY,[TransactionDate],GETDATE()) BETWEEN 90 AND 365 THEN 'Stale Transaction'
	WHEN DATEDIFF(DAY,[TransactionDate],GETDATE()) >= 365 THEN 'Archived Transaction'
	END AS [Transaction Age]
, CASE  
	WHEN [TransactionAmount] BETWEEN 100 AND 1000 THEN 'Silver Customer'
	WHEN [TransactionAmount] BETWEEN 1000 AND 3000 THEN 'Gold Customer'
	WHEN [TransactionAmount] >= 3000 THEN 'Platinum Customer'
	ELSE 'Regular Customer'
	END AS CustomerClass
	  , [OutstandingBalance]
      , [IsFinalized]
	  , [FinalizationDate]
      , [LastEditedBy]
      , [LastEditedWhen]
  FROM [WideWorldImporters].[Sales].[CustomerTransactions];
-- Listing 8: Case Expression for Transaction by Comparing Two Columns  
SELECT TOP (20) 
CASE CustomerID 
	WHEN 1 THEN 'Tailspin Toys'
	WHEN 401 THEN 'Wingtip Toys'
	WHEN 801 THEN 'Eric Torres'
	WHEN 802 THEN 'Cosmina Vlad'
	WHEN 803 THEN 'Bala Dixit'
	WHEN 804 THEN 'Alekxandrs Reikstins'
	WHEN 805 THEN 'Ratan Podder'
	WHEN 806 THEN 'Shi Tu'
	WHEN 807 THEN 'Gunnar Lohmus'
	WHEN 808 THEN 'Jackson Kolios'
ELSE 'Unknown Customer'
END CustomerName
      , [InvoiceID]
, CASE  
	WHEN DATEDIFF(DAY,[TransactionDate],[FinalizationDate]) < 30 THEN 'Prompt Transaction'
	WHEN DATEDIFF(DAY,[TransactionDate],[FinalizationDate]) BETWEEN 30 AND 90 THEN 'Delayed Transaction'
	WHEN DATEDIFF(DAY,[TransactionDate],[FinalizationDate]) BETWEEN 90 AND 365 THEN 'Serverely Delayed Transaction'
	WHEN DATEDIFF(DAY,[TransactionDate],[FinalizationDate]) >= 365 THEN 'Orphaned Transaction'
	END AS [Transaction Response]
, CASE  
	WHEN [TransactionAmount] BETWEEN 100 AND 1000 THEN 'Silver Customer'
	WHEN [TransactionAmount] BETWEEN 1000 AND 3000 THEN 'Gold Customer'
	WHEN [TransactionAmount] >= 3000 THEN 'Platinum Customer'
	ELSE 'Regular Customer'
	END AS CustomerClass
, [OutstandingBalance]
      	, [IsFinalized]
, [FinalizationDate]
      	, [LastEditedBy]
      	, [LastEditedWhen]
  FROM [WideWorldImporters].[Sales].[CustomerTransactions];

CASE-uitdrukkingen buiten de SELECT-lijst

We kunnen ook CASE-expressies gebruiken in SET-statements, UPDATE-statements, WHERE-clausules, HAVING-clausules en ORDER BY-clausules.

De Update-instructie in Listing 9 werkt het OutstandingBalance bij kolom met rijen met vier verschillende klant-ID's met verschillende waarden. Deze instructie komt overeen met het schrijven van vijf verschillende update-instructies voor elke CASE en vervolgens de ELSE.

-- Listing 9: Update Statement with CASE Expression 
  UPDATE Sales.CustomerTransactions
  SET OutstandingBalance =
	(CASE 
		WHEN CustomerID = 832 THEN 100.00
		WHEN CustomerID = 803 THEN 150.00
		WHEN CustomerID = 905 THEN 200.00
		WHEN CustomerID = 976 THEN 70.00
		ELSE 50.00
	END
	);
	SELECT TOP 20 * FROM Sales.CustomerTransactions;

Conclusie

Met SQL en T-SQL kunt u waarden die in een kolom zijn opgeslagen, vervangen door de gewenste waarden. In dit artikel hebben we eenvoudige en doorzochte CASE-expressies met voorbeelden onderzocht.

CASE-expressies kunnen worden gebruikt in SELECT-clausules, SET-instructies, UPDATE-statements, WHERE-, HAVING- en ORDER BY-clausules.

Referenties

GEVAL
Datum- en tijdfuncties


  1. SQL Server ontbrekende index

  2. Oracle prestatie- en afstemmingsquiz

  3. Fout ORA-00932 bij gebruik van een select met unie- en CLOB-velden

  4. Hoe de INSERT()-functie werkt in MariaDB