我想要做這樣的事情CTE內部SQL 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之後兩次在IF
和ELSE
聲明中寫出SELECT
聲明。
我想要做這樣的事情CTE內部SQL 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之後兩次在IF
和ELSE
聲明中寫出SELECT
聲明。
如果可能的CTE「定義」,找到一種方式來完全避免if
聲明。
E.g.在這樣一個簡單的例子,如你的問題:
;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 */
應該通常可以組成一個或多個不同的查詢到最終UNION ALL
CTE,而是採用if
- 畢竟,無論是查詢被混合的絕無論如何都有兼容的結果集,對於你原來的問題是有道理的。
你不能這麼做 - CTE 必須在之後緊跟一個恰好一個可引用它的SQL語句。您不能從使用它的語句中拆分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
不能拆分爲它的使用(select * from cte
)
@MartinSmith:我害怕的是(但無法找到的文檔一個明確的說法):-(因此打消了我的部分。 –
我知道CTE必須緊跟一個sql語句,但我正在尋找一種解決方法,我不想編寫重複的select語句。 – MegaMind
@MegaMind:there **沒有辦法解決這個問題* * - 這是CTE定義的工作方式 –
with cte (...) select from cte ...
是單個語句。不是'遵循'的聲明,它是是聲明的一部分。你要求將陳述分成兩部分,這顯然是不可能的。
作爲一般規則,SQL對DRY和避免代碼重複等事情來說是非常不友好的語言。試圖使代碼更易於維護,更具可讀性,或者只是簡單地嘗試保存一些按鍵就可以(並且通常會)導致嚴重的運行時性能損失(例如,試圖將CTE移動到表值函數UDF中)。最簡單的事情就是咬下子彈(這次和未來......)並寫出CTE兩次。有時將CTE物化爲#temp表格,然後在#temp表格中運行,但只有有時是。
這status-quo is unfortunate,但你可以從design by committee期望的一切......
Damien的一個非常好的解決方法,使用'Union ALL'並在where子句中添加'if'條件過濾器 對於性能,我建議使用過濾器作爲第一個條款在'Where' –
@Damien_The_Unbeliever,你能否詳細說明爲什麼我們應該避免'IF'? –
@NikitaSilverstruk - 這不是一個絕對的禁止,更多的是一般指南 - 如果你試圖產生一個結果集,你應該嘗試制定如何在單個查詢中生成結果集,然後讓優化器計算出最佳結果生成它,而不是手動將查詢分解爲塊。正如你可以從marc_s的答案中看到的那樣,使用if的替代方法最終有兩個查詢,它們之間有重複。 –