Einführung
CASE-Ausdrücke in SQL Server werden für die Substitution von Spaltenwerten verwendet, um die Ergebnismengen auf eine bestimmte Weise oder einfache Abfragen darzustellen. Anwendungsfälle für solche Befehle sind vielfältig.
Beispielsweise gibt es eine Spalte mit dem Abteilungscode, aber Sie möchten den Namen der Abteilung anstelle des Codes anzeigen. Sie könnten dies erreichen, indem Sie einen JOIN mit einer anderen Tabelle durchführen, die die Abteilungsdetails enthält. Nehmen wir jedoch an, Sie möchten die Abfrage relativ einfach halten. Ein weiterer Anwendungsfall wäre die Rückgabe spezifischer Werte für den berechneten Wertesatz. Berechnete Spalten passen nicht, wenn die anzugebenden Bedingungssätze nicht identisch sind.
Typischerweise haben die CASE-Ausdrücke von SQL Server die in Listing 1 gezeigte Form.
-- 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;
Einfacher Fall und gesuchter Fall
Die beiden oben beschriebenen Szenarien passen recht gut in die beiden Arten von CASE-Ausdrücken, die in SQL Server verfügbar sind. Ein einfacher CASE-Ausdruck erlaubt nur Gleichheitsprüfungen. Ein gesuchter CASE-Ausdruck erlaubt sogar boolesche Ausdrücke.
Beachten Sie, dass die Ergebnisse eines CASE-Ausdrucks in eine einzelne Spalte passen. Beachten Sie auch, dass wir den Spaltennamen direkt nach der CASE-Klausel im einfachen CASE-Ausdruck angeben. Im gesuchten CASE-Ausdruck müssen wir jedoch den Spaltennamen für jeden booleschen Ausdruck angeben. Sehen wir uns einige Beispiele an.
Szenarioumgebung
Bei unserer Untersuchung des CASE-Ausdrucks verwenden wir die bekannte WideWorldImporters-Beispieldatenbank. Dort verwenden wir die Sales.CustomerTransactions Tabelle, um verschiedene Szenarien der CASE-Ausdrucksanwendung zu demonstrieren. Wie bei T-SQL üblich, ist es möglich, ähnliche Ergebnisse mit anderen Techniken wie JOINs zu erhalten, aber wir konzentrieren uns auf eine Tabelle, um die CASE-Ausdrucksfähigkeiten zu zeigen.
Beachten Sie, dass man die verarbeiteten Daten verstehen muss, um CASE-Ausdrücke verwenden zu können. Beispielsweise müssen wir wissen, was jeder Kunde Code bedeutet, die Daten für den Endbenutzer sinnvoller darzustellen. In unseren Fällen können wir die Informationen aus anderen Tabellen abrufen.
Listing 2 ist eine einfache Abfrage, die zeigt, wie die Daten in der Tabelle aussehen. Abbildung 1 zeigt uns einen Ausgabeteil.
-- 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] ;
Rückgabe von Kundennamen basierend auf Kunden-ID
In diesem Beispiel möchten wir den Namen jedes Kunden basierend auf dem Kundencode anzeigen. Wir erhalten die Kundennamen aus einer anderen Tabelle mit einer JOIN-Abfrage. Auch hier verwenden wir den CASE-Ausdruck, um zu demonstrieren, was dieser Ansatz bewirken kann.
-- 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;
Mit diesen Informationen schreiben wir eine einfache CASE-Abfrage, um Daten allein aus Sales.CustomerTransactions abzurufen (siehe Listing 4). Abbildung 3 hebt die von der Abfrage zurückgegebenen Namen hervor.
Beachten Sie das Auftreten von „Unbekannten Kunden“ in der Ausgabe. Diese Kunden sind im eigentlichen Sinne keine Unbekannten. Wir haben sie nicht, weil wir ihre CustomerID in unserem CASE-Ausdruck nicht berücksichtigt haben. Dies unterstreicht die Notwendigkeit, die Daten bei der Verwendung von CASE-Ausdrücken zu verstehen.
-- 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];
Rückgabe der Kundenklasse basierend auf dem Transaktionsbetrag
In diesem Beispiel verwenden wir den Ausdruck Searched CASE, um anzuzeigen, welcher unserer Kunden hinsichtlich des Transaktionswerts wertvoller ist.
Wir klassifizieren die Kunden basierend auf dem Transaktionswert in drei Gruppen – Normal, Silber, Gold und Platin. Das ist natürlich vereinfacht. In einem realen Szenario müssten wir ihre Transaktionen über einen bestimmten Zeitraum summieren. In diesem Fall verwenden wir nur eine Teilmenge von Daten, um die CASE-Ausdrucksfähigkeiten zu zeigen.
-- 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];
Rückgabe des Wochentags mit verschachtelten CASE-Ausdrücken
Wir fahren mit den Beispielen fort, indem wir ein Beispiel hinzufügen, das uns mitteilt, welcher Wochentag das Transaktionsdatum war (siehe Listing 6). Beachten Sie, dass wir dies mit einer viel einfacheren Form der Abfrage mit der DATENAME-Funktion anstelle der DATEPART-Funktion hätten erreichen können.
-- 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];
Kennzeichnung von Transaktionen nach Datum
Mit dem Code in Listing 7 und 8 können wir Transaktionen basierend auf der Differenz zwischen dem aktuellen Datum und dem Transaktionsdatum kennzeichnen. Dies gilt auch für die Differenz zwischen dem Transaktionsdatum und einer anderen Spalte. Daher können wir andere Spalten als die, mit denen wir arbeiten, als Eingabe für einen booleschen Ausdruck einführen.
-- 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-Ausdrücke außerhalb der SELECT-Liste
Wir können CASE-Ausdrücke auch in SET-Anweisungen, UPDATE-Anweisungen, WHERE-Klauseln, HAVING-Klauseln und ORDER BY-Klauseln verwenden.
Die Update-Anweisung in Listing 9 aktualisiert den OutstandingBalance Spalte von Zeilen mit vier verschiedenen Kunden-IDs mit unterschiedlichen Werten. Diese Anweisung entspricht dem Schreiben von fünf verschiedenen Aktualisierungsanweisungen für jeden CASE und dann dem 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;
Schlussfolgerung
Mit SQL und T-SQL können Sie in einer Spalte gespeicherte Werte durch Ihre gewünschten Werte ersetzen. In diesem Artikel haben wir einfache und durchsuchte CASE-Ausdrücke anhand von Beispielen untersucht.
CASE-Ausdrücke können für SELECT-Klauseln, SET-Anweisungen, UPDATE-Anweisungen, WHERE-, HAVING- und ORDER BY-Klauseln verwendet werden.
Referenzen
FALL
Datums- und Zeitfunktionen