SQL Serverで入れ子になったcaseステートメントロジックを実行する最良の方法


185

SQLクエリを作成しています。返される列のいくつかは、かなり多くの条件に応じて計算する必要があります。

現在、ネストされたcaseステートメントを使用していますが、面倒です。より良い(より整理された、そして/または読みやすい)方法はありますか?

(Microsoft SQL Server、2005を使用しています)


簡単な例:

SELECT
    col1,
    col2,
    col3,
    CASE
        WHEN condition 
        THEN
            CASE
                WHEN condition1 
                THEN
                    CASE 
                        WHEN condition2
                        THEN calculation1
                        ELSE calculation2
                    END
                ELSE
                    CASE 
                        WHEN condition2
                        THEN calculation3
                        ELSE calculation4
                    END
            END
        ELSE 
            CASE 
                WHEN condition1 
                THEN 
                    CASE
                        WHEN condition2 
                        THEN calculation5
                        ELSE calculation6
                    END
                ELSE
                    CASE
                        WHEN condition2 
                        THEN calculation7
                        ELSE calculation8
                    END
            END            
    END AS 'calculatedcol1',
    col4,
    col5 -- etc
FROM table

こんにちは、入れ子になったクエリを上手にインデントするツール(SQLinFormなど)を使用しましたか?
グイド2013年

入れ子のより良いフォーマット方法を教えてくれてCASE WHEN
ありがとう

これが効率的で役立つ場合は確かにありますが、一般的に、SQLクエリからロジックを遠ざけたいと思います。後世のための単なるヒント。
tschwab

回答:


188

あなたはある種のCOALESCEトリックを試すことができます、例えば:

コアレスを選択(
  CASE WHEN条件1 THEN計算1 ELSE NULL END、
  CASE WHEN条件2 THEN計算2 ELSE NULL END、
  等...
)

いいですね、私はちょうどそれが短絡することを確認するためにテストしました、そしてそれがそうであることを発見して驚きました。したがって、condition1がゼロによる除算をチェックした場合、condition2でそれを実行しても安全であるように見えます。これが保証されているかどうかはわかりません。
Cade Roux、

13
1つの問題点は、ケースの1つが正当にNULLを返したい場合、それはもはや不可能であることです。
Chris KL、

8
これは素晴らしいトリックですが、CASEステートメントを単独で使用した場合よりもパフォーマンスが低下する可能性があることに注意してください。これは、コミュニティの追加セクションの「ドキュメント」に記載されています-msdn.microsoft.com/en-us/library/ms190349.aspx。このソリューションを実装したとき、私のDBAはハンマーを下ろしました...
shanabus 2013年

これは単なるケースステートメント(@beachの答え)より優れているのはいつですか?
ロニーオーバーバイ2014

この回答の列の名前を変更する方法..たとえば、「calculation1」を「CAL1」に名前変更したい場合...構文的にどのように可能ですか?
Renacent

89

それらすべてのケースを1つにまとめます。


SELECT
    col1,
    col2,
    col3,
    CASE
        WHEN condition1 THEN calculation1 
        WHEN condition2 THEN calculation2
        WHEN condition3 THEN calculation3
        WHEN condition4 THEN calculation4
        WHEN condition5 THEN calculation5
        ELSE NULL         
    END AS 'calculatedcol1',
    col4,
    col5 -- etc
FROM table

31

複数の条件を組み合わせて、状況を回避できます。

CASE WHEN condition1 = true AND condition2 = true THEN calculation1 
     WHEN condition1 = true AND condition2 = false 
     ELSE 'what so ever' END,

21

私は個人的にこのようにして、埋め込まれたCASE式を制限します。何が起こっているのかを説明するためにコメントも入れておきます。複雑すぎる場合は、機能に分解します。

SELECT
    col1,
    col2,
    col3,
    CASE WHEN condition THEN
      CASE WHEN condition1 THEN
        CASE WHEN condition2 THEN calculation1
        ELSE calculation2 END
      ELSE
        CASE WHEN condition2 THEN calculation3
        ELSE calculation4 END
      END
    ELSE CASE WHEN condition1 THEN 
      CASE WHEN condition2 THEN calculation5
      ELSE calculation6 END
    ELSE CASE WHEN condition2 THEN calculation7
         ELSE calculation8 END
    END AS 'calculatedcol1',
    col4,
    col5 -- etc
FROM table

11

ネストされた「複雑な」ケース文の簡単な解決策を次に示します。-ネストされたケースの複雑な式

select  datediff(dd,Invdate,'2009/01/31')+1 as DaysOld, 
    case when datediff(dd,Invdate,'2009/01/31')+1 >150 then 6 else
        case when datediff(dd,Invdate,'2009/01/31')+1 >120 then 5 else 
            case when datediff(dd,Invdate,'2009/01/31')+1 >90 then 4 else 
                case when datediff(dd,Invdate,'2009/01/31')+1 >60 then 3 else 
                    case when datediff(dd,Invdate,'2009/01/31')+1 >30 then 2 else 
                        case when datediff(dd,Invdate,'2009/01/31')+1 >30 then 1 end 
                    end
                end
            end
        end
    end as Bucket
from rm20090131atb

すべてのcase文にend文があることを確認してください


5
他の人に解読してもらいたい場合は、回答をフォーマットすることができます。
IsmailS 2010年

6

複数の条件を組み合わせて、パフォーマンスのオーバーヘッドを減らすことができます。

ケースを実行する3つの変数abcがあるとします。これは次のようにして行うことができます。

CASE WHEN a = 1 AND b = 1 AND c = 1 THEN '1'
     WHEN a = 0 AND b = 0 AND c = 1 THEN '0'
ELSE '0' END,

5

ユーザー定義関数は、少なくともロジックを非表示にするために、より適切に機能します。複数のクエリでこれを行う必要がある場合


2

私はこれを調べたところ、すべての回答がとてもクールでしたが、@ deejersからの回答に追加したいと考えています

    SELECT
    col1,
    col2,
    col3,
    CASE
        WHEN condition1 THEN calculation1 
        WHEN condition2 THEN calculation2
        WHEN condition3 THEN calculation3
        WHEN condition4 THEN calculation4
        WHEN condition5 THEN calculation5         
    END AS 'calculatedcol1',
    col4,
    col5 -- etc
FROM table

ELSEは必須ではないのでオプションにすることができ、多くのシナリオで非常に役立ちます。


2

この例はあなたに役立つかもしれません、写真はifと複数の内部ifループがある場合のSQL caseステートメントがどのように見えるかを示しています

ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.