CASE (Transact-SQL)
適用対象: SQL Server Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Analytics Platform System (PDW) Microsoft Fabric の SQL 分析エンドポイント Microsoft Fabric Warehouse Microsoft Fabric SQL Database
一連の条件を評価して、考えられる結果式のうちの 1 つを返します。
CASE
式には 2 つの形式があります。
単純
CASE
式は、1 つの式を一連の単純式と比較して結果を決定します。検索
CASE
式は、一連のブール式を評価して結果を判定します。
どちらの形式も、ELSE 引数 (省略可) をサポートしています。
CASE
は、有効な式を使用できる任意のステートメントや句で使用できます。 たとえば、SELECT、UPDATE、DELETE、SET などのステートメントや、<select_list>、IN、WHERE、ORDER BY、HAVING などの句で CASE
を使用できます。
構文
SQL Server、Azure SQL Database、Azure Synapse Analytics の構文。
-- 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
Parallel Data Warehouse の構文。
CASE
WHEN when_expression THEN result_expression [ ...n ]
[ ELSE else_result_expression ]
END
引数
input_expression
単純 CASE
形式を使用した場合に評価される式。 input_expression は任意の有効な式です。
WHEN when_expression
単純 CASE
形式を使用した場合に input_expression と比較される単純式。 when_expression は任意の有効な式です。 input_expression と各 when_expression のデータ型は同一であるか、暗黙的な変換によって同一の型になる必要があります。
THEN result_expression
input_expression = when_expression が TRUE に評価されるとき、または Boolean_expression が TRUE に評価されるときに返される式。 result_expression は任意の有効な式です。
ELSE else_result_expression
比較操作の評価がいずれも TRUE でなかった場合に返される式。 この引数を省略し、比較操作のいずれも TRUE でなかった場合、CASE
は NULL を返します。 else_result_expression は任意の有効な式です。 else_result_expression とすべての result_expression のデータ型は同一であるか、暗黙的な変換によって同一の型になる必要があります。
WHEN Boolean_expression
検索 CASE
形式を使用したときに評価されるブール式。 Boolean_expression は任意の有効なブール式です。
戻り値の型
result_expressions および省略可能な else_result_expression の一連の型から、最も優先順位の高い型を返します。 詳細については、「データ型の優先順位 (Transact-SQL)」を参照してください。
戻り値
単純 CASE 式:
単純 CASE
式では、最初の式と、各 WHEN 句の式が等しいかどうかが比較されます。 等しかった場合は、THEN 句の式が返されます。
実行できるのは、等しいかどうかのチェックだけです。
各 WHEN 句の input_expression = when_expression を指定した順序で評価します。
TRUE に評価される最初の input_expression = when_expression の result_expression を返します。
input_expression = when_expression の評価がいずれも TRUE でなかった場合、SQL Server データベース エンジン は、ELSE 句が指定されていれば else_result_expression を、ELSE 句が指定されていない場合は NULL を返します。
検索 CASE 式:
各 WHEN 句の Boolean_expression を指定した順序で評価します。
TRUE と評価された最初の Boolean_expression の result_expression を返します。
Boolean_expression の評価がいずれも TRUE でなかった場合、データベース エンジン は、ELSE 句が指定されていれば else_result_expression を、ELSE 句が指定されていない場合は NULL を返します。
解説
SQL Server では、CASE
式に入れ子にできるのは 10 レベルだけです。
CASE
式を使って、Transact-SQL のステートメント、ステートメント ブロック、ユーザー定義関数、ストアド プロシージャの実行のフローを制御することはできません。 フロー制御言語の一覧については、フロー制御言語 (Transact-SQL) に関する記事を参照してください。
CASE
式では、その条件が順番に評価され、最初に条件が満たされた時点で停止します。 状況によっては、式の結果を CASE
式が入力として受け取る前に、式が評価されます。 こうした式の評価中にエラーが発生する可能性もあります。 CASE
式の WHEN 引数で指定されている集計式は、最初に評価されてから CASE
式に渡されます。 たとえば、次のクエリでは、MAX 集計値を生成する際に 0 除算エラーが発生します。 これが発生するのは、CASE
式が評価される前です。
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;
GO
WHEN 条件が上から順に評価されるという前提に依存できるのは、スカラー式 (スカラー値を返す非相関サブクエリを含む) の場合だけであり、集計式の場合は依存できません。
また、THEN または ELSE 句の式の少なくとも 1 つが NULL 定数ではないことも確認する必要があります。 複数の結果式から NULL が返されてもかまいませんが、これらのすべてを明示的に NULL 定数にすることはできません。 すべての結果式で NULL 定数が使われている場合は、エラー 8133 が返されます。
例
A. SELECT ステートメントで単純 CASE 式を使用する
SELECT
ステートメント内では、単純 CASE
式は等しいかどうかのチェックだけを実行できます。これ以外の比較操作は実行できません。 CASE
式を使用して、製品ラインのカテゴリの表示をわかりやすいものに変更する例を次に示します。
USE AdventureWorks2022;
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. SELECT ステートメントで検索 CASE 式を使用する
SELECT
ステートメント内では、検索 CASE
式は比較値に基づいて結果セット内で値を置換できます。 次の例では、表示価格を、製品の価格範囲に基づいたテキスト コメントとして表示しています。
USE AdventureWorks2022;
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. ORDER BY 句で CASE を使用する
次の例では、ORDER BY 句で CASE
式を使い、指定された列の値に基づいて行の並べ替え順序を決定しています。 最初の例では、SalariedFlag
テーブルの HumanResources.Employee
列の値を評価します。 SalariedFlag
が 1 に設定されている従業員は BusinessEntityID
の降順で、 SalariedFlag
が 0 に設定されている従業員は BusinessEntityID
の昇順で返されます。 2 番目の例では、TerritoryName
列が 'United States' と等しい場合は結果セットが CountryRegionName
列の順序に従って並べ替えられ、他のすべての列は CountryRegionName
の順序に従って並べ替えられます。
SELECT BusinessEntityID,
SalariedFlag
FROM HumanResources.Employee
ORDER BY CASE SalariedFlag
WHEN 1 THEN BusinessEntityID
END DESC,
CASE
WHEN SalariedFlag = 0 THEN BusinessEntityID
END;
GO
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;
GO
D. UPDATE ステートメントで CASE を使用する
次の例では、UPDATE ステートメントで CASE
式を使いSalariedFlag
が 0 に設定されている従業員の VacationHours
列に設定される値を決めています。 VacationHours
の値を 10 時間差し引くと値がマイナスになる場合は VacationHours
の値を 40 時間増やします。それ以外の場合は、VacationHours
の値を 20 時間増やします。 OUTPUT 句は、この処理の前後の休暇の値を表示するために使用されています。
USE AdventureWorks2022;
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;
GO
E. SET ステートメントで CASE を使用する
次の例では、テーブル値関数 dbo.GetContactInfo
の SET ステートメントで CASE
式を使っています。 AdventureWorks2022
データベースでは、人に関連するデータはすべて Person.Person
テーブルに格納されています。 たとえば、従業員、仕入先の代表者、消費者などはすべて人に関連するデータとして扱われます。 この関数は、指定された BusinessEntityID
の名と姓、およびそのユーザーの連絡先の種類を返します。 ContactType
列に表示される値は、SET ステートメント内の CASE
式により、Employee
、Vendor
、または Customer
のどのテーブルに BusinessEntityID
列が含まれているかに基づいて決定されます。
USE AdventureWorks2022;
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);
GO
F. HAVING 句で CASE を使用する
次の例では、HAVING 句で CASE
式を使って、SELECT ステートメントから返される行を制限しています。 このステートメントは、HumanResources.Employee
テーブル内の各役職の時給を返します。 HAVING 句により、役職は、固定給従業員については最高時給が 40 ドルを超えている場合のみ、非固定給従業員については 15 ドルを超えている場合のみに制限されます。
USE AdventureWorks2022;
GO
SELECT JobTitle,
MAX(ph1.Rate) AS MaximumRate
FROM HumanResources.Employee AS e
INNER JOIN HumanResources.EmployeePayHistory AS ph1
ON e.BusinessEntityID = ph1.BusinessEntityID
GROUP BY JobTitle
HAVING (
MAX(CASE
WHEN SalariedFlag = 1 THEN ph1.Rate
ELSE NULL
END) > 40.00
OR MAX(CASE
WHEN SalariedFlag = 0 THEN ph1.Rate
ELSE NULL
END) > 15.00
)
ORDER BY MaximumRate DESC;
GO
例: Azure Synapse Analytics、Analytics Platform System (PDW)
G. SELECT ステートメントで CASE 式を使用する
SELECT ステートメント内では、CASE
式により比較値に基づいて結果セット内の値を置換できます。 CASE
式を使用して、製品ラインのカテゴリの表示をわかりやすいものに変更する例を次に示します。 値が存在しない場合は、テキスト "Not for sale" が表示されます。
-- Uses AdventureWorks
SELECT ProductAlternateKey,
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,
EnglishProductName
FROM dbo.DimProduct
ORDER BY ProductKey;
GO
H. UPDATE ステートメントで CASE を使用する
次の例では、UPDATE ステートメントで CASE
式を使いSalariedFlag
が 0 に設定されている従業員の VacationHours
列に設定される値を決めています。 VacationHours
の値を 10 時間差し引くと値がマイナスになる場合は VacationHours
の値を 40 時間増やします。それ以外の場合は、VacationHours
の値を 20 時間増やします。
-- Uses AdventureWorks
UPDATE dbo.DimEmployee
SET VacationHours = (
CASE
WHEN ((VacationHours - 10.00) < 0) THEN VacationHours + 40
ELSE (VacationHours + 20.00)
END
)
WHERE SalariedFlag = 0;
GO