sql >> Databasteknik >  >> RDS >> Sqlserver

Använda CASE-uttryck i SQL Server

Introduktion

CASE-uttryck i SQL Server används för att ersätta kolumnvärdena för att presentera resultatuppsättningarna på ett visst sätt eller enkla frågor. Användningsfallen för sådana kommandon är olika.

Det finns till exempel en kolumn som innehåller avdelningskoden, men du vill visa avdelningens namn istället för koden. Du kan uppnå det genom att göra en JOIN med en annan tabell som innehåller avdelningsinformationen. Men låt oss anta att du vill hålla frågan relativt enkel. Ett annat användningsfall skulle vara att returnera specifika värden för de beräknade värdena. Beräknade kolumner skulle inte passa om de villkor som ska specificeras inte är desamma.

Vanligtvis har SQL Server CASE-uttryck den form som visas i Lista 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;

Enkla fall och sökta fall

De två scenarierna som beskrivs ovan passar ganska bra in i de två typerna av CASE-uttryck som finns tillgängliga i SQL Server. Ett enkelt CASE-uttryck tillåter endast jämställdhetskontroller. Ett sökt CASE-uttryck tillåter även booleska uttryck.

Observera att resultaten av ett CASE-uttryck passar in i en enda kolumn. Observera också att vi anger kolumnnamnet precis efter CASE-satsen i Simple CASE-uttrycket. I det sökta CASE-uttrycket måste vi dock ange kolumnnamnet för varje booleskt uttryck. Låt oss utforska några exempel.

Scenariomiljö

I vår utforskning av CASE-uttrycket ska vi använda den välkända WideWorldImporters exempeldatabasen. Där använder vi Sales.CustomerTransactions tabell för att visa olika scenarier för CASE-uttrycksapplikationen. Som är vanligt med T-SQL är det möjligt att få liknande resultat med andra tekniker, såsom JOINs, men vi fokuserar på en tabell för att visa CASE-uttrycksmöjligheterna.

Observera att man måste förstå den data som hanteras för att använda CASE-uttryck. Vi måste till exempel veta vad varje kund kod betyder att representera data med mer mening för slutanvändaren. I våra fall kan vi hämta informationen från andra tabeller.

Lista 2 är en enkel fråga som visar hur data i tabellen ser ut. Figur 1 visar en utgångsdel.

-- 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] ;

Returnerande kundnamn baserat på kund-ID

I det här exemplet vill vi visa namnet på varje kund baserat på kundkoden. Vi hämtar kunders namn från en annan tabell med hjälp av en JOIN-fråga. Återigen använder vi CASE-uttrycket för att visa vad detta tillvägagångssätt kan göra.

-- 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;

Med denna information skriver vi en enkel CASE-fråga för att hämta data från enbart Sales.CustomerTransactions (se lista 4). Figur 3 markerar namnen som returneras av frågan.

Observera förekomsten av "Okända kunder" i utgången. I verklig mening är dessa kunder inte okända. Vi har inte dem eftersom vi inte tillgodosede deras kund-ID i vårt CASE-uttryck. Detta stödjer behovet av att förstå data när du använder CASE-uttryck.

-- 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];

Återlämna kundklassen baserat på transaktionsbeloppet

I det här exemplet använder vi uttrycket Searched CASE för att visa vilken av våra kunder som är mer värdefull när det gäller transaktionsvärdet.

Vi klassificerar kunderna i tre grupper – Regular, Silver, Gold och Platinum, baserat på transaktionsvärdet. Naturligtvis är detta förenklat. I ett verkligt scenario skulle vi behöva summera deras transaktioner under en given period. I det här fallet använder vi endast en dataundergrupp för att visa CASE-uttrycksfunktionerna.

-- 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];

Återställa veckodagen med kapslade CASE-uttryck

Vi fortsätter med proverna genom att lägga till ett prov som berättar vilken veckodag som transaktionsdatumet var (se lista 6). Observera att vi kunde ha uppnått detta med en mycket enklare form av frågan med funktionen DATENAME snarare än DATEPART-funktionen.

-- 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];

Märkning av transaktioner baserat på datum

Med hjälp av koden i listorna 7 och 8 kan vi märka transaktioner baserat på skillnaden mellan det aktuella datumet och transaktionsdatumet. Det gäller även skillnaden mellan transaktionsdatum och en annan kolumn. Därför kan vi introducera andra kolumner än de vi arbetar med som en input till ett booleskt uttryck.

  -- 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-uttryck utanför SELECT-listan

Vi kan också använda CASE-uttryck i SET-satser, UPDATE-satser, WHERE-satser, HAVING-satser och ORDER BY-satser.

Uppdateringssatsen i Lista 9 uppdaterar OutstandingBalance kolumn med rader med fyra olika kund-ID med olika värden. Detta uttalande motsvarar att skriva fem olika uppdateringssatser för varje CASE och sedan 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;

Slutsats

SQL och T-SQL låter dig ersätta värden lagrade i en kolumn med dina önskade värden. I den här artikeln har vi utforskat Simple och Searched CASE-uttryck med exempel.

CASE-uttryck kan användas på SELECT-satser, SET-satser, UPDATE-satser, WHERE, HAVING och ORDER BY-satser.

Referenser

FALL
Datum- och tidsfunktioner


  1. Hur man ändrar MySQL-serverns tidszon

  2. Paginering i SQL Server med OFFSET/FETCH

  3. ORA 00904 Fel:Ogiltig identifierare

  4. En översikt över PostgreSQL 13 libpq sslpassword anslutningsparametrar