Click to Rate and Give Feedback
MSDN
MSDN Library
SQL Server
SQL Server 2008 R2
Database Engine
Technical Reference
 CASE (Transact-SQL)
Community Content
In this section
Statistics Annotations (7)
Collapse All/Expand All Collapse All
Other versions are also available for the following:
CASE (Transact-SQL)

Evaluates a list of conditions and returns one of multiple possible result expressions.

The CASE expression has two formats:

  • The simple CASE expression compares an expression to a set of simple expressions to determine the result.

  • The searched CASE expression evaluates a set of Boolean expressions to determine the result.

Both formats support an optional ELSE argument.

CASE can be used in any statement or clause that allows a valid expression. For example, you can use CASE in statements such as SELECT, UPDATE, DELETE and SET, and in clauses such as select_list, IN, WHERE, ORDER BY, and HAVING.

Topic link icon Transact-SQL Syntax Conventions

Simple CASE expression: 
CASE input_expression 
     WHEN when_expression THEN result_expression [ ...n ] 
     [ ELSE else_result_expression ] 
END 
Searched CASE expression:
CASE
     WHEN Boolean_expression THEN result_expression [ ...n ] 
     [ ELSE else_result_expression ] 
END
input_expression

Is the expression evaluated when the simple CASE format is used. input_expression is any valid expression.

WHEN when_expression

Is a simple expression to which input_expression is compared when the simple CASE format is used. when_expression is any valid expression. The data types of input_expression and each when_expression must be the same or must be an implicit conversion.

THEN result_expression

Is the expression returned when input_expression equals when_expression evaluates to TRUE, or Boolean_expression evaluates to TRUE. result expression is any valid expression.

ELSE else_result_expression

Is the expression returned if no comparison operation evaluates to TRUE. If this argument is omitted and no comparison operation evaluates to TRUE, CASE returns NULL. else_result_expression is any valid expression. The data types of else_result_expression and any result_expression must be the same or must be an implicit conversion.

WHEN Boolean_expression

Is the Boolean expression evaluated when using the searched CASE format. Boolean_expression is any valid Boolean expression.

Returns the highest precedence type from the set of types in result_expressions and the optional else_result_expression. For more information, see Data Type Precedence (Transact-SQL).

Return Values

Simple CASE expression:

The simple CASE expression operates by comparing the first expression to the expression in each WHEN clause for equivalency. If these expressions are equivalent, the expression in the THEN clause will be returned.

  • Allows only an equality check.

  • Evaluates input_expression, and then in the order specified, evaluates input_expression = when_expression for each WHEN clause.

  • Returns the result_expression of the first input_expression = when_expression that evaluates to TRUE.

  • If no input_expression = when_expression evaluates to TRUE, the SQL Server Database Engine returns the else_result_expression if an ELSE clause is specified, or a NULL value if no ELSE clause is specified.

Searched CASE expression:

  • Evaluates, in the order specified, Boolean_expression for each WHEN clause.

  • Returns result_expression of the first Boolean_expression that evaluates to TRUE.

  • If no Boolean_expression evaluates to TRUE, the Database Engine returns the else_result_expression if an ELSE clause is specified, or a NULL value if no ELSE clause is specified.

SQL Server allows for only 10 levels of nesting in CASE expressions.

The CASE expression cannot be used to control the flow of execution of Transact-SQL statements, statement blocks, user-defined functions, and stored procedures. For a list of control-of-flow methods, see Control-of-Flow Language (Transact-SQL).

The CASE statement evaluates its conditions sequentially and stops with the first condition whose condition is satisfied. In some situations, an expression is evaluated before a CASE statement receives the results of the expression as its input. Errors in evaluating these expressions are possible. Aggregate expressions that appear in WHEN arguments to a CASE statement are evaluated first, then provided to the CASE statement. For example, the following query produces a divide by zero error when producing the value of the MAX aggregate. This occurs prior to evaluating the CASE expression.

Transact-SQL
WITH Data (value) AS 
( 
SELECT 0 
UNION ALL 
SELECT 1 
) 
SELECT 
   CASE 
      WHEN MIN(value) <= 0 THEN 0 
      WHEN MAX(1/value) >= 100 THEN 1 
   END 
FROM Data ;

You should only depend on order of evaluation of the WHEN conditions for scalar expressions (including non-correlated sub-queries that return scalars), not for aggregate expressions.

A. Using a SELECT statement with a simple CASE expression

Within a SELECT statement, a simple CASE expression allows for only an equality check; no other comparisons are made. The following example uses the CASE expression to change the display of product line categories to make them more understandable.

Transact-SQL
USE AdventureWorks2008R2;
GO
SELECT   ProductNumber, Category =
      CASE ProductLine
         WHEN 'R' THEN 'Road'
         WHEN 'M' THEN 'Mountain'
         WHEN 'T' THEN 'Touring'
         WHEN 'S' THEN 'Other sale items'
         ELSE 'Not for sale'
      END,
   Name
FROM Production.Product
ORDER BY ProductNumber;
GO

B. Using a SELECT statement with a searched CASE expression

Within a SELECT statement, the searched CASE expression allows for values to be replaced in the result set based on comparison values. The following example displays the list price as a text comment based on the price range for a product.

Transact-SQL
USE AdventureWorks2008R2;
GO
SELECT   ProductNumber, Name, 'Price Range' = 
      CASE 
         WHEN ListPrice =  0 THEN 'Mfg item - not for resale'
         WHEN ListPrice < 50 THEN 'Under $50'
         WHEN ListPrice >= 50 and ListPrice < 250 THEN 'Under $250'
         WHEN ListPrice >= 250 and ListPrice < 1000 THEN 'Under $1000'
         ELSE 'Over $1000'
      END
FROM Production.Product
ORDER BY ProductNumber ;
GO

C. Using CASE to replace the IIf function that is used in Microsoft Access

CASE provides functionality that is similar to the IIf function in Microsoft Access. The following example shows a simple query that uses IIf to provide an output value for the TelephoneInstructions column in an Access table that is named db1.ContactInfo.

SELECT FirstName, LastName, TelephoneNumber, 
     IIf(IsNull(TelephoneInstructions),"Any time",
     TelephoneInstructions) AS [When to Contact]
FROM db1.ContactInfo; 

The following example uses CASE to provide an output value for the TelephoneSpecialInstructions column in the AdventureWorks2008R2 view Person.vAdditionalContactInfo.

Transact-SQL
USE AdventureWorks2008R2;
GO
SELECT FirstName, LastName, TelephoneNumber, 'When to Contact' = 
     CASE
          WHEN TelephoneSpecialInstructions IS NULL THEN 'Any time'
          ELSE TelephoneSpecialInstructions
     END
FROM Person.vAdditionalContactInfo;

D. Using CASE in an ORDER BY clause

The following examples uses the CASE expression in an ORDER BY clause to determine the sort order of the rows based on a given column value. In the first example, the value in the SalariedFlag column of the HumanResources.Employee table is evaluated. Employees that have the SalariedFlag set to 1 are returned in order by the EmployeeID in descending order. Employees that have the SalariedFlag set to 0 are returned in order by the EmployeeID in ascending order. In the second example, the result set is ordered by the column TerritoryName when the column CountryRegionName is equal to 'United States' and by CountryRegionName for all other rows.

Transact-SQL
SELECT BusinessEntityID, SalariedFlag
FROM HumanResources.Employee
ORDER BY CASE SalariedFlag WHEN 1 THEN BusinessEntityID END DESC
        ,CASE WHEN SalariedFlag = 0 THEN BusinessEntityID END;
GO

Transact-SQL
SELECT BusinessEntityID, LastName, TerritoryName, CountryRegionName
FROM Sales.vSalesPerson
WHERE TerritoryName IS NOT NULL
ORDER BY CASE CountryRegionName WHEN 'United States' THEN TerritoryName
         ELSE CountryRegionName END;

E. Using CASE in an UPDATE statement

The following example uses the CASE expression in an UPDATE statement to determine the value that is set for the column VacationHours for employees with SalariedFlag set to 0. When subtracting 10 hours from VacationHours results in a negative value, VacationHours is increased by 40 hours; otherwise, VacationHours is increased by 20 hours. The OUTPUT clause is used to display the before and after vacation values.

Transact-SQL
USE AdventureWorks2008R2;
GO
UPDATE HumanResources.Employee
SET VacationHours = 
    ( CASE
         WHEN ((VacationHours - 10.00) < 0) THEN VacationHours + 40
         ELSE (VacationHours + 20.00)
       END
    )
OUTPUT Deleted.BusinessEntityID, Deleted.VacationHours AS BeforeValue, 
       Inserted.VacationHours AS AfterValue
WHERE SalariedFlag = 0; 

F. Using CASE in a SET statement

The following example uses the CASE expression in a SET statement in the table-valued function dbo.GetContactInfo. In the AdventureWorks2008R2 database, all data related to people is stored in the Person.Person table. For example, the person may be an employee, vendor representative, or a customer. The function returns the first and last name of a given BusinessEntityID and the contact type for that person.The CASE expression in the SET statement determines the value to display for the column ContactType based on the existence of the BusinessEntityID column in the Employee, Vendor, or Customer tables.

Transact-SQL
	USE AdventureWorks2008R2;
	GO
	CREATE FUNCTION dbo.GetContactInformation(@BusinessEntityID int)
	RETURNS @retContactInformation TABLE 
	(
	BusinessEntityID int NOT NULL,
	FirstName nvarchar(50) NULL,
	LastName nvarchar(50) NULL,
	ContactType nvarchar(50) NULL,
    PRIMARY KEY CLUSTERED (BusinessEntityID ASC)
) 
AS 
-- Returns the first name, last name and contact type for the specified contact.
BEGIN
    DECLARE 
        @FirstName nvarchar(50), 
        @LastName nvarchar(50), 
        @ContactType nvarchar(50);

    -- Get common contact information
    SELECT 
        @BusinessEntityID = BusinessEntityID, 
		@FirstName = FirstName, 
        @LastName = LastName
    FROM Person.Person 
    WHERE BusinessEntityID = @BusinessEntityID;

    SET @ContactType = 
        CASE 
            -- Check for employee
            WHEN EXISTS(SELECT * FROM HumanResources.Employee AS e 
                WHERE e.BusinessEntityID = @BusinessEntityID) 
                THEN 'Employee'

            -- Check for vendor
            WHEN EXISTS(SELECT * FROM Person.BusinessEntityContact AS bec
                WHERE bec.BusinessEntityID = @BusinessEntityID) 
                THEN 'Vendor'

            -- Check for store
            WHEN EXISTS(SELECT * FROM Purchasing.Vendor AS v          
                WHERE v.BusinessEntityID = @BusinessEntityID) 
                THEN 'Store Contact'

            -- Check for individual consumer
            WHEN EXISTS(SELECT * FROM Sales.Customer AS c 
                WHERE c.PersonID = @BusinessEntityID) 
                THEN 'Consumer'
        END;

    -- Return the information to the caller
    IF @BusinessEntityID IS NOT NULL 
    BEGIN
        INSERT @retContactInformation
        SELECT @BusinessEntityID, @FirstName, @LastName, @ContactType;
    END;

    RETURN;
END;
GO

SELECT BusinessEntityID, FirstName, LastName, ContactType
FROM dbo.GetContactInformation(2200);
GO
SELECT BusinessEntityID, FirstName, LastName, ContactType
FROM dbo.GetContactInformation(5);

G. Using CASE in a HAVING clause

The following example uses the CASE expression in a HAVING clause to restrict the rows returned by the SELECT statement. The statement returns the the maximum hourly rate for each job title in the HumanResources.Employee table. The HAVING clause restricts the titles to those that are held by men with a maximum pay rate greater than 40 dollars or women with a maximum pay rate greater than 42 dollars.

Transact-SQL
USE AdventureWorks2008R2;
GO
SELECT JobTitle, MAX(ph1.Rate)AS MaximumRate
FROM HumanResources.Employee AS e
JOIN HumanResources.EmployeePayHistory AS ph1 ON e.BusinessEntityID = ph1.BusinessEntityID
GROUP BY JobTitle
HAVING (MAX(CASE WHEN Gender = 'M' 
        THEN ph1.Rate 
        ELSE NULL END) > 40.00
     OR MAX(CASE WHEN Gender  = 'F' 
        THEN ph1.Rate  
        ELSE NULL END) > 42.00)
ORDER BY MaximumRate DESC;

Tags What's this?: Add a tag
Community Content   What is Community Content?
Add new content RSS  Annotations
Using CASE in ORDER BY with multiple columns      S_Javed85   |   Edit   |   Show History
Declare @Sort As Int
Set @Sort = 0
select * from Product
Order By
Case When @Sort = 0 Then Column1 Else Column2 End,
Case When @Sort = 0 Then Column2 Else Column1 End,
Column3
Tags What's this?: Add a tag
Flag as ContentBug
Using CASE in ORDER BY with multiple columns      ghendric ... S_Javed85   |   Edit   |   Show History
Is there a way to use CASE in the ORDER BY to sort on multiple columns based on a condition or variable instead of one column or the other? EX:

ORDER BY
     CASE WHEN @sortorder = 1 then COL1, COL2, COL3
     ELSE COL2, COL1, COL3
     END
==============================================================================================
Check This One

Declare @Sort As Int
Set @Sort = 0
select * from Product
Order By
Case When @Sort = 0 Then Column1 Else Column2 End,
Case When @Sort = 0 Then Column2 Else Column1 End,
Column3
Tags What's this?: Add a tag
Flag as ContentBug
None of the result expressions in a CASE specification can be NULL.      Jose Chinchilla aka SQLJoe   |   Edit   |   Show History

The following caveat need to be taken into consideration:

  • If no else_result_expression is specified or if else_result_expression is set to
    return an explicit NULL, at least one result_expression has to be specified to
    return a non-explicit NULL.
Tags What's this?: Add a tag
Flag as ContentBug
Using CASE in a GROUP BY clause , also Using LIKE      Hasham Niaz   |   Edit   |   Show History

Just to let know that you can use CASE with GROUP BY Clause , it's just not mentioned here so i thin it would be nice to mention it on MSDN and also we can use LIKE for comparision inside WHEN.

--Using CASE in a GROUP BY clause , also Using LIKE

USE AdventureWorks
GO

SELECT CASE
WHEN Title LIKE '%Account%' THEN 'Account'
WHEN Title LIKE '%Chief%' THEN 'Chief'
WHEN Title LIKE '%Database%' THEN 'Database'
WHEN Title LIKE '%Human Resources%' THEN 'Human Resources'
WHEN Title LIKE '%Netowrk%' THEN 'Network'
WHEN Title LIKE '%Production%' THEN 'Production'
WHEN Title LIKE '%Quality Assurance%' THEN 'Quality Assurance'
WHEN Title LIKE '%Research%' THEN 'Research'
WHEN Title LIKE '%Vice President%' THEN 'Vice President'
ELSE 'No Specific Title'
END AS Title
, COUNT(EmployeeID) AS NumberOfEmployee
FROM HumanResources.Employee
GROUP BY CASE
WHEN Title LIKE '%Account%' THEN 'Account'
WHEN Title LIKE '%Chief%' THEN 'Chief'
WHEN Title LIKE '%Database%' THEN 'Database'
WHEN Title LIKE '%Human Resources%' THEN 'Human Resources'
WHEN Title LIKE '%Netowrk%' THEN 'Network'
WHEN Title LIKE '%Production%' THEN 'Production'
WHEN Title LIKE '%Quality Assurance%' THEN 'Quality Assurance'
WHEN Title LIKE '%Research%' THEN 'Research'
WHEN Title LIKE '%Vice President%' THEN 'Vice President'
ELSE 'No Specific Title'
END

--Title NumberOfEmployee
------------------- ----------------
--Account 8
--Chief 3
--Database 2
--Human Resources 3
--No Specific Title 82
--Production 180
--Quality Assurance 6
--Research 4
--Vice President 2

--(9 row(s) affected)
Tags What's this?: Add a tag
Flag as ContentBug
Using IN Clause while comparing condition in CASE WEHN Clause      Hasham Niaz   |   Edit   |   Show History
Here is another tip, you can use IN Clause inside CASE WHEN Expression when comparing.

--Using IN Clause while comparing condition in CASE WEHN Clause

USE AdventureWorks
GO

SELECT CASE
WHEN Title IN('Mr.','Sr.','Sra.') THEN 'Mr.'
WHEN Title IN('Mrs.','Ms.','Ms') THEN 'Ms.'
ELSE 'N/A'
END AS Title
, FirstName , LastName
FROM Person.Contact

--Title FirstName LastName
------- ---------------- --------------------------------------------------
--Mr. Gustavo Achong
--Ms. Catherine Abel
--Ms. Kim Abercrombie
--Mr. Humberto Acevedo
--Mr. Pilar Ackerman

--(5 row(s) affected)
Tags What's this?: Add a tag
Flag as ContentBug
Left-to-right evaluation is not always honored      aaronbertrand   |   Edit   |   Show History
The documentation currently states:

"Evaluates, in the order specified, Boolean_expression for each WHEN clause."

Due to at least two different known and confirmed bugs, current versions of SQL Server do not *always* follow this behavior *in all cases.* Meaning that in certain scenarios, the n+1th argument of a case expression may be evaluated even if the nth argument evaluates to true. While this behavior may be corrected in future versions of SQL Server, it can't be 100% relied on today. Note that this can also apply to certain COALESCE scenarios as well (which get expanded to CASE expressions), so it's not necessarily the case that you can always rely on COALESCE to short circuit, for much the same reasons.

Before you rely on this left-to-right short-circuiting, please read all of the discussion at the following links:

http://stackoverflow.com/questions/7473045/does-sql-server-read-all-of-a-coalesce-function-even-if-the-first-argument-is-not

http://bartduncansql.wordpress.com/2011/03/03/dont-depend-on-expression-short-circuiting-in-t-sql-not-even-with-case/

http://connect.microsoft.com/SQLServer/feedback/details/649957/
Tags What's this?: Add a tag
Flag as ContentBug
SQL SERVER 2005      GOKULNATH   |   Edit   |   Show History
Excellent Examples
Tags What's this?: Add a tag
Flag as ContentBug
Processing
© 2012 Microsoft. All rights reserved. Terms of Use | Trademarks | Privacy Statement
Page view tracker