18


4

SQL Server 2008 - SELECT句のCase / Ifステートメント

私はこのように実行することになっているクエリを持っています -

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
}

これは、値に応じて異なる列を選択するためだけの冗長なコードです。 代替案はありますか?

6 回答


22


あなたはCASE文を探しています

MSDNからコピーされた例:

AdventureWorksを使用します。選択商品番号、カテゴリ=ケースProductLine「R」「ロード」「M」「THEN」「WHEN」「TO」「WHEN」「S」「その他」の販売商品「ELSE」の場合販売終了の場合製造からの製品。製品注文製品番号で。 GO


19


ここでちょっと注意してください、あなたは実際には最適化のために3つの別々のSELECTSを持つ方が良いかもしれないことに注意してください。 単一のSELECTがある場合、生成されたプランはすべての列col1、col2、col3、col7、col8などを投影する必要がありますが、ランタイム@varの値に応じて、いくつかだけが必要です。 これは、非クラスタ化インデックスがSELECTによって投影されたすべての列をカバーしないため、不要なクラスタ化インデックスの検索を実行する計画になる可能性があります。

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

もちろん、これはデータモデルの実際のスキーマと正確なクエリに依存しますが、これは単なる頭の問題であるため、手続き型プログラミングの命令型思考の枠組みを宣言型のSQLの世界に持ち込まないでください。


9


のようなものを試してください

SELECT CASE var WHEN xyz THEN col1 WHEN zyx THEN col2 ELSE col7 col1として終了...

つまり、条件式を使用して値を選択してから列の名前を変更します。

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


2


単純なCASE式:

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

検索したCASE式:

Boolean_expression THEN result_expression [... n]の場合[else else_result_expression] END

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


0


CASEがその答えですが、返す列ごとに個別のcaseステートメントを用意する必要があります。 WHERE句が同じである限り、それを複数のクエリに分割してもそれほどメリットはありません。

例:

SELECT case @var WHEN 'xyz' THEN col1 WHEN 'zyx' THEN col2 ELSE col7終了、CASE @var WHEN 'xyz' THEN col2 WHEN 'zyx' THEN col3 ELSE col8 END FROMテーブル
...


0


最も明白な解決策はすでにリストされています。 クエリがどこにあるかによります アプリケーションコードでは、IFステートメントを常に使用できるわけではなく、多くの列が条件付きになるとインラインCASEステートメントが面倒になることがあります。 Col1、Col3、Col7が同じタイプで、Col2、Col4、Col8が同じタイプであると仮定すると、次のようになります。

SELECT Col1、Col2からtblどこへ@Varのような 'xyz' UNION ALL SELECT Col3、Col4からtblどこで@Varのような 'zyx' UNIONすべてSELECT Col7、Col8からtblのどこから@Var NOT LIKE 'xyz'と@Var NOT zyx '

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