次の方法で共有


CASE (Transact-SQL)

適用対象:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceAzure Synapse AnalyticsAnalytics Platform System (PDW)Microsoft Fabric の SQL 分析エンドポイントMicrosoft Fabric のウェアハウスMicrosoft Fabric プレビューの SQL データベース

一連の条件を評価して、考えられる結果式のうちの 1 つを返します。

CASE 式には 2 つの形式があります。

  • simpleCASE 式は、式を一連の単純式と比較して結果を決定します。

  • searchedCASE 式は、一連のブール式を評価して結果を決定します。

どちらの形式でも、省略可能な ELSE 引数がサポートされます。

CASE は、有効な式を使用できる任意のステートメントや句で使用できます。 たとえば、SELECTUPDATEDELETESETなどのステートメントや、<select_list>INWHEREORDER BYHAVINGなどの句でCASEを使用できます。

Transact-SQL 構文表記規則

Syntax

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

Arguments

input_expression

単純 CASE 形式を使用した場合に評価される式。 input_expression は任意の有効なです。

WHEN when_expression

単純 形式を使用した場合に CASE と比較される単純式。 when_expression は任意の有効な式です。 input_expression と各 when_expression のデータ型は同一であるか、暗黙的な変換によって同一の型になる必要があります。

に、result_expression

input_expressionが等しい場合返される式when_expressionTRUEに評価されるか、Boolean_expressionTRUEに評価されます。 result_expression は任意の有効なです。

ELSE else_result_expression

比較操作が TRUEに評価されない場合に返される式。 この引数を省略しても比較操作が TRUEと評価されない場合、 CASENULLを返します。 else_result_expression は任意の有効な式です。 else_result_expression とすべての result_expression のデータ型は同一であるか、暗黙的な変換によって同一の型になる必要があります。

WHEN Boolean_expression

検索 CASE 形式を使用したときに評価されるブール式。 Boolean_expression は任意の有効なブール式です。

戻り値の型

result_expressions および省略可能な else_result_expression の一連の型から、最も優先順位の高い型を返します。 詳細については、「 Data 型の優先順位」を参照してください。

戻り値

単純な CASE 式

単純な CASE 式は、最初の式を各 WHEN 句の式と比較して等価性を得ることで動作します。 これらの式が等しい場合は、 THEN 句の式が返されます。

  • 実行できるのは、等しいかどうかのチェックだけです。

  • 指定された順序で、各 WHEN 句のinput_expression = when_expressionを評価します。

  • TRUE に評価される最初のinput_expression = when_expressionのresult_expressionを返します。

  • input_expression = when_expressionTRUEに評価されない場合、SQL Server データベース エンジンは、ELSE句が指定されている場合はelse_result_expressionを返し、ELSE句が指定されていない場合はNULL値を返します。

検索された CASE 式

  • 指定した順序で、各WHEN句のBoolean_expressionを評価します。

  • TRUE に評価される最初のBoolean_expressionのresult_expressionを返します。

  • TRUEに評価されるBoolean_expressionがない場合、データベース エンジンはELSE句が指定されている場合はelse_result_expressionを返し、ELSE句が指定されていない場合はNULL値を返します。

Remarks

SQL Server では、CASE 式に入れ子にできるのは 10 レベルだけです。

CASE 式を使って、Transact-SQL のステートメント、ステートメント ブロック、ユーザー定義関数、ストアド プロシージャの実行のフローを制御することはできません。 フロー制御方法の一覧については、「 フロー制御」を参照してください。

CASE 式では、その条件が順番に評価され、最初に条件が満たされた時点で停止します。 状況によっては、式の結果を CASE 式が入力として受け取る前に、式が評価されます。 こうした式の評価中にエラーが発生する可能性もあります。 CASEWHEN引数に表示される集計式は、最初に評価され、次に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 が返されます。

Examples

この記事のコード サンプルでは、AdventureWorks2022 または AdventureWorksDW2022 サンプル データベースを使用します。このサンプル データベースは、Microsoft SQL Server サンプルとコミュニティ プロジェクト ホーム ページからダウンロードできます。

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 の昇順で返されます。

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

2 番目の例では、TerritoryName 列が 'United States' と等しい場合は結果セットが CountryRegionName 列の順序に従って並べ替えられ、他のすべての列は CountryRegionName の順序に従って並べ替えられます。

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.GetContactInfoSET ステートメントでCASE式を使用します。 AdventureWorks2022 データベースでは、人に関連するデータはすべて Person.Person テーブルに格納されています。 たとえば、従業員、ベンダー担当者、または顧客などです。 この関数は、特定のBusinessEntityIDの名 (FirstName) とファミリ名 (LastName) とそのユーザーの連絡先の種類を返します。 SET ステートメントのCASE式は、EmployeeVendor、またはCustomerテーブルにBusinessEntityID列が存在するかどうかに基づいて、列ContactTypeに表示する値を決定します。

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

G. 入れ子になった CASE 式を使用して結果を分類する

次の例では、入れ子になった CASE 式を使用して、 ListPriceに基づいて製品を分類します。 製品定価が 1,000 ドルを超える場合は、 High-endと見なされます。 残りの製品は、ProductLineListPriceに基づいて、入れ子になったCASE式に分類されます。

USE AdventureWorks2022;
GO

SELECT 
    ProductNumber,
    Name,
    ListPrice,
    PriceCategory = 
        CASE 
            WHEN ListPrice > 1000 THEN 'High-end'
            ELSE 
                CASE ProductLine
                    WHEN 'R' THEN
                        CASE 
                            WHEN ListPrice > 500 THEN 'Premium Road'
                            ELSE 'Standard Road'
                        END
                    WHEN 'M' THEN
                        CASE 
                            WHEN ListPrice > 500 THEN 'Premium Mountain'
                            ELSE 'Standard Mountain'
                        END
                    WHEN 'T' THEN 'Touring'
                    ELSE 'Other'
                END
        END
FROM Production.Product
ORDER BY ListPrice DESC;

例: Azure Synapse Analytics、Analytics Platform System (PDW)

H. SELECT ステートメントで CASE 式を使用する

SELECT ステートメント内では、CASE式を使用すると、比較値に基づいて結果セット内の値を置き換えることができます。 CASE 式を使用して、製品ラインのカテゴリの表示をわかりやすいものに変更する例を次に示します。 値が存在しない場合は、テキスト Not for sale が表示されます。

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

I. UPDATE ステートメントで CASE を使用する

次の例では、UPDATE ステートメントのCASE式を使用して、SalariedFlagが 0 に設定されている従業員の列VacationHoursに設定されている値を決定します。 VacationHours の値を 10 時間差し引くと値がマイナスになる場合は VacationHours の値を 40 時間増やします。それ以外の場合は、VacationHours の値を 20 時間増やします。

UPDATE dbo.DimEmployee
SET VacationHours = (
        CASE
            WHEN ((VacationHours - 10.00) < 0) THEN VacationHours + 40
            ELSE (VacationHours + 20.00)
            END
        )
WHERE SalariedFlag = 0;
GO