私はこのようなことをしたい
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
したくありません。IF
ELSE
私はこのようなことをしたい
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
したくありません。IF
ELSE
可能であれば、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 ALL
cteに構成することが可能であるif
必要があります。結局のところ、元の質問を理解するには、結合される両方のクエリに互換性のある結果セットが必要です。
それはできません。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
)
は単一のステートメントwith cte (...) select from cte ...
です。ステートメントが「後に続く」のではなく、ステートメントの一部です。ステートメントを 2 つに分割しようとしていますが、これは明らかに不可能です。
原則として、SQL は DRY のようなものやコードの繰り返しを避けることには非常に不向きな言語です。コードをより保守しやすく、読みやすくしようとしたり、単純にいくつかのキーストロークを節約しようとしたりすると、実行時のパフォーマンスに重大なペナルティが発生する可能性があります (通常はそうなります) (たとえば、CTE をテーブル値関数 UDF に移動しようとするなど)。最も簡単な方法は、弾丸をかじって (今回、そして将来...)、CTE を 2 回記述することです。CTE を #temp テーブルに実体化してから #temp テーブルを操作することが理にかなっている場合もありますが、場合によっては.
この現状は残念ですが、委員会による設計に期待できるすべてです...