6

私はこのようなことをしたい

declare @a int=1
if (@a=1)
with cte as 
(
select UserEmail from UserTable 
)
else
with cte as
(
select UserID from UserTable
)
select * from cte

これは単なる例であり、実際のクエリははるかに複雑です。そのため、CTE の後にステートメントを 2 回記述SELECTしたくありません。IFELSE

4

3 に答える 3

13

可能であれば、ifステートメントを完全に回避する方法を見つけてください。

たとえば、あなたの質問のような些細な例では:

;with CTE as (
      select UserEmail from UserTable where @a = 1
      union all
      select UserID from UserTable where @a != 1 or @a is null
)
select /* single select statement here */

通常、使用する代わりに、1 つ以上の個別のクエリを最終的なUNION ALLcteに構成することが可能であるif必要があります。結局のところ、元の質問を理解するには、結合される両方のクエリに互換性のある結果セットが必要です。

于 2012-06-25T07:16:54.133 に答える
6

それはできません。CTE の直後に、それを参照できる SQL ステートメントが 1 つだけ続く必要があります。CTE の「定義」を、それを使用するステートメントから分割することはできません。

したがって、次のようにする必要があります。

declare @a int=1

if (@a=1)
    with cte as 
    (
       select UserEmail from UserTable 
    )
    select * from cte

else

    with cte as
    (
       select UserID from UserTable
    )
    select * from cte

CTE の「定義」を分割して使用することはできません ( select * from cte)

于 2012-06-25T06:49:02.277 に答える
4

単一のステートメントwith cte (...) select from cte ...です。ステートメントが「後に続く」のではなく、ステートメントの一部です。ステートメントを 2 つに分割しようとしていますが、これは明らかに不可能です。

原則として、SQL は DRY のようなものやコードの繰り返しを避けることには非常に不向きな言語です。コードをより保守しやすく、読みやすくしようとしたり、単純にいくつかのキーストロークを節約しようとしたりすると、実行時のパフォーマンスに重大なペナルティが発生する可能性があります (通常はそうなります) (たとえば、CTE をテーブル値関数 UDF に移動しようとするなど)。最も簡単な方法は、弾丸をかじって (今回、そして将来...)、CTE を 2 回記述することです。CTE を #temp テーブルに実体化してから #temp テーブルを操作することが理にかなっている場合もありますが、場合によっては.

この現状は残念ですが、委員会による設計に期待できるすべてです...

于 2012-06-25T08:50:08.413 に答える