sql >> データベース >  >> RDS >> Sqlserver

SQLServerでのCASE式の使用

    はじめに

    SQL ServerのCASE式は、特定の方法または単純なクエリで結果セットを表示するための列値の置換に使用されます。このようなコマンドの使用例はさまざまです。

    たとえば、部門コードを含む列がありますが、コードではなく部門の名前を表示したいとします。部門の詳細を含む別のテーブルでJOINを実行することでそれを達成できます。ただし、クエリを比較的単純にしたいとします。別のユースケースは、計算された値セットの特定の値を返すことです。指定する条件のセットが同じでない場合、計算列は適合しません。

    通常、SQLServerのCASE式の形式はリスト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;

    単純なケースと検索されたケース

    上記の2つのシナリオは、SQLServerで使用可能な2種類のCASE式に非常によく適合します。単純なCASE式では、同等性チェックのみが可能です。 Searched CASE式では、ブール式も使用できます。

    CASE式の結果は1つの列に収まることに注意してください。また、SimpleCASE式のCASE句の直後に列名を指定していることに注意してください。ただし、検索されたCASE式では、各ブール式の列名を指定する必要があります。いくつかの例を見てみましょう。

    シナリオ環境

    CASE式の調査では、よく知られているWideWorldImportersサンプルデータベースを使用します。そこで、 Sales.CustomerTransactionsを使用します CASE式アプリケーションのさまざまなシナリオを示す表。 T-SQLで一般的であるように、JOINなどの他の手法を使用して同様の結果を得ることができますが、CASE式の機能を示すために1つのテーブルに焦点を当てます。

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

    顧客IDに基づいて顧客名を返す

    この例では、顧客コードに基づいて各顧客の名前を表示します。 JOINクエリを使用して、別のテーブルから顧客の名前を取得します。繰り返しになりますが、CASE式を使用して、このアプローチで何ができるかを示しています。

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

    この情報を使用して、Sales.CustomerTransactionsのみからデータを取得するための単純なCASEクエリを記述します(リスト4を参照)。図3は、クエリによって返される名前を示しています。

    「不明な顧客」の発生を観察します 出力で。本当の意味で、これらの顧客は不明ではありません。 CASE式でCustomerIDに対応していなかったため、これらはありません。これは、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式を使用して、トランザクション値に関してどの顧客がより価値があるかを示します。

    取引額に基づいて、お客様をレギュラー、シルバー、ゴールド、プラチナの3つのグループに分類します。もちろん、これは単純です。実際のシナリオでは、特定の期間のトランザクションを合計する必要があります。この場合、CASE式の機能を示すためにデータサブセットのみを使用しています。

    -- 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を参照)。これは、DATEPART関数ではなくDATENAME関数を使用したはるかに単純な形式のクエリを使用して実現できた可能性があることに注意してください。

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

    SELECTリスト外のCASE式

    SETステートメント、UPDATEステートメント、WHERE句、HAVING句、およびORDERBY句でCASE式を使用することもできます。

    リスト9のUpdateステートメントは、 OutstandingBalanceを更新します。 値が異なる4つの異なる顧客IDを持つ行の列。このステートメントは、CASEごとに5つの異なる更新ステートメントを記述し、次に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式について説明しました。

    CASE式は、SELECT句、SETステートメント、UPDATEステートメント、WHERE、HAVING、およびORDERBY句で使用できます。

    参照

    場合
    日付と時刻の関数


    1. MySQLで小数点を変更する

    2. MSSQL2019のUDF内での予期しない@@rowcountの動作

    3. XMLをCLOB列からXMLType列に変換するときにエラーが発生しました

    4. Oracleウォレットを使用する場合の正しいJDBCURL構文は何ですか?