2009-07-13 40 views
18

が、私はこのように実行することになっての問合せがある場合 -SQL Server 2008の - ケース/ SELECT句で文

 

If(var = xyz) 
    SELECT col1, col2 
ELSE IF(var = zyx) 
    SELECT col2, col3 
ELSE 
    SELECT col7,col8 

FROM 

. 
. 
. 

をどのように私は、各句のために別々のクエリを記述することなく、T-SQLでこれを達成できますか?現在、私はちょうど値に応じて異なる列を選択するために、冗長なコードだけたくさんだこと

 

IF (var = xyz) { 
    Query1 
} 
ELSE IF (var = zyx) { 
    Query2 
} 
ELSE { 
    Query3 
} 

として、それを実行していますよ。 代替手段はありますか?条件式を使用し、

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

答えて

18

ここで注意してほしいのは、実際に最適化の理由から3つの別々の選択肢があるほうがよいということです。 1つのSELECTがある場合、生成されたプランはすべての列col1、col2、col3、col7、col8などを投影する必要がありますが、ランタイム@varの値に応じていくつかのみが必要です。これにより、クラスタ化されていないインデックスがSELECTによって投影されたすべての列をカバーしないため、不必要なクラスタード・インデックス・ルックアップを行う計画が発生する可能性があります。

一方、必要な列のみを投影する3つの別々のSELECTSは、それぞれの場合に投影された列だけをカバーする非クラスタ化インデックスの恩恵を受ける可能性があります。

もちろん、これはデータモデルの実際のスキーマと正確なクエリに依存しますが、これは単なる見本ですので、手続き型プログラミングの心構えフレームをSQLの宣言的な世界に持ち込まないでください。

+3

+1非常に良好な観測 –

22

あなたは

http://msdn.microsoft.com/en-us/library/ms181765.aspx

例は、MSDNからコピーCASE文を探しています値を選択し、列の名前を変更します。

また、クエリテールを共有するために、ある種の動的SQLハックを構築することもできます。私は前にiBatisでこれをやった。

+0

が見えます! :) –

+0

私は(簡単に)間違っている可能性がありますので、まだn00bですが、これは実際に質問に答えるものではないと思います。 OPは、**複数の列を選択する方法を尋ねましたが、複数の値のオプションのうちの1つを単一の列に割り当てることはできませんでした。私がOPだったら、@JoelMansfordからの答えが最も正しいと思われるでしょう。私がいれば/私が間違っている理由を教えてください! – dah97765

9

試してみてください何か言い換えれば

SELECT 
    CASE var 
     WHEN xyz THEN col1 
     WHEN zyx THEN col2 
     ELSE col7 
    END AS col1, 
    ... 

のような:

0

CASEが答えですが、返す列ごとに別々のcase文が必要です。 WHERE句が同じであれば、複数のクエリに分割することはあまり効果的ではありません。

例:

SELECT 
    CASE @var 
     WHEN 'xyz' THEN col1 
     WHEN 'zyx' THEN col2 
     ELSE col7 
    END, 
    CASE @var 
     WHEN 'xyz' THEN col2 
     WHEN 'zyx' THEN col3 
     ELSE col8 
    END 
FROM Table 
... 
0

最も明白な解決策は既に記載されています。クエリがどこに置かれているかによって(つまりアプリケーションコード内で)、IF文を常に使用することはできず、多くの列が条件付きになる場合はインラインCASE文が痛いことがあります。 と仮定するのCol1 + COL3 + COL7は、同じタイプであり、同様にCol2に、COL4 + Col8あなたがこれを行うことができます。このよう

SELECT Col1, Col2 FROM tbl WHERE @Var LIKE 'xyz' 
UNION ALL 
SELECT Col3, Col4 FROM tbl WHERE @Var LIKE 'zyx' 
UNION ALL 
SELECT Col7, Col8 FROM tbl WHERE @Var NOT LIKE 'xyz' AND @Var NOT LIKE 'zyx' 

キャッシュを計画に関して、いくつかのパフォーマンス上の利点がある単一のコマンドです。また、クエリオプティマイザは、@ Varがストレージエンジンに触れずに適切な値と一致しない文を素早く排除します。

2

単純CASE式:​​

CASE input_expression 
    WHEN when_expression THEN result_expression [ ...n ] 
    [ ELSE else_result_expression ] 
END 

検索CASE式:​​

CASE 
    WHEN Boolean_expression THEN result_expression [ ...n ] 
    [ ELSE else_result_expression ] 
END 

参考:私はninja'dてきたようにhttp://msdn.microsoft.com/en-us/library/ms181765.aspx