Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Използване на CASE изрази в SQL Server

Въведение

CASE изразите в SQL Server се използват за заместване на стойностите на колоните за представяне на резултантните набори по определен начин или прости заявки. Случаите на използване на такива команди са различни.

Например, има колона, съдържаща кода на отдела, но искате да покажете името на отдела, а не кода. Можете да го постигнете, като направите JOIN с друга таблица, съдържаща подробности за отдела. Нека обаче приемем, че искате да запазите заявката сравнително проста. Друг случай на използване би бил връщането на конкретни стойности за изчисления набор от стойности. Изчислените колони няма да се поберат, ако наборите от условия, които трябва да посочите, не са еднакви.

Обикновено CASE изразите на SQL Server имат формата, показана в листинг 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;

Прост и търсен случай

Двата описания по-горе сценария се вписват доста добре в двата типа CASE изрази, налични в SQL Server. Прост CASE израз позволява само проверки на равенството. Търсен CASE израз позволява дори булеви изрази.

Имайте предвид, че резултатите от CASE израз се вписват в една колона. Също така имайте предвид, че ние посочваме името на колоната непосредствено след клаузата CASE в израза Simple CASE. Въпреки това, в търсения CASE израз трябва да посочим името на колоната за всеки булев израз. Нека разгледаме някои примери.

Сценарна среда

В нашето изследване на израза CASE ще използваме добре познатата примерна база данни WideWorldImporters. Там ще използваме Sales.CustomerTransactions таблица за демонстриране на различни сценарии на приложението CASE израз. Както е обичайно с T-SQL, е възможно да се получат подобни резултати, като се използват други техники, като JOIN, но ние се фокусираме върху една таблица, за да покажем възможностите за CASE израз.

Имайте предвид, че човек трябва да разбере обработваните данни, за да използва CASE изрази. Например, трябва да знаем какво е всеки клиент код означава представяне на данните с повече смисъл за крайния потребител. В нашите случаи можем да получим информацията от други таблици.

Списък 2 е проста заявка, показваща как изглеждат данните в таблицата. Фигура 1 ни показва изходна част.

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

Връщане на имена на клиенти въз основа на идентификационния номер на клиента

В този пример искаме да покажем името на всеки клиент въз основа на клиентския код. Получаваме имената на клиенти от друга таблица с помощта на заявка JOIN. Отново използваме CASE Expression, за да демонстрираме какво може да направи този подход.

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

Имайки тази информация, ние пишем проста CASE заявка за извличане на данни само от Sales.CustomerTransactions (вижте листинг 4). Фигура 3 подчертава имената, върнати от заявката.

Наблюдавайте появата на „Неизвестни клиенти“ в изхода. В реалния смисъл тези клиенти не са непознати. Нямаме ги, защото не сме се погрижили за техния CustomerID в нашия CASE израз. Това подкрепя необходимостта от разбиране на данните при използване на CASE изрази.

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

Връщане на класа на клиента въз основа на сумата на транзакцията

В този пример използваме израза Searched CASE, за да покажем кой от нашите клиенти има по-голяма стойност по отношение на стойността на транзакцията.

Ние класифицираме клиентите в три групи – обикновени, сребърни, златни и платинени, въз основа на стойността на транзакцията. Разбира се, това е опростено. В реален сценарий ще трябва да сумираме техните транзакции за даден период. В този случай използваме само подмножество от данни, за да покажем възможностите на CASE Expression.

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

Връщане на деня от седмицата с помощта на вложени CASE изрази

Продължаваме с пробите, като добавяме извадка, която ни казва кой ден от седмицата е датата на транзакцията (вижте листинг 6). Имайте предвид, че бихме могли да постигнем това, използвайки много по-проста форма на заявката, използвайки функцията DATENAME, а не функцията 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];

Етикетиране на транзакции въз основа на дата

Използвайки кода в листинги 7 и 8, можем да маркираме транзакции въз основа на разликата между текущата дата и датата на транзакцията. Прилага се и за разликата между датата на транзакцията и друга колона. Следователно можем да въведем колони, различни от тези, с които работим, като вход за булев израз.

  -- 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 изрази извън списъка SELECT

Можем също да използваме изрази CASE в изрази SET, изрази UPDATE, клаузи WHERE, клаузи HAVING и клаузи ORDER BY.

Изявлението Update в листинг 9 актуализира OutstandingBalance колона от редове с четири различни идентификатора на клиенти с различни стойности. Това изявление е еквивалентно на писане на пет различни оператора за актуализиране за всеки CASE и след това за 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;

Заключение

SQL и T-SQL ви позволяват да замените стойностите, съхранени в колона, с желаните от вас стойности. В тази статия разгледахме прости и търсени CASE изрази с примери.

Изразите CASE могат да се използват в клаузи SELECT, SET, UPDATE, WHERE, HAVING и ORDER BY.

Препратки

СЛУЧАЙ
Функции за дата и час


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Има ли разлика в производителността между CTE, подзаявка, временна таблица или таблична променлива?

  2. SQL производителност:WHERE срещу WHERE(ROW_NUMBER)

  3. CEILING() Примери в SQL Server

  4. Искам да използвам оператор CASE, за да актуализирам някои записи в sql server 2005

  5. INFORMATION_SCHEMA срещу sysobjects