我有2個表格。從兩個表中選擇一個
讓我們打電話給他們Table1
和Table2
。兩個表具有相同的結構和數據類型。
Table1
是交易表,Table2
是歷史數據表。
我需要做這樣的事情:
Select * from case when 'transnational' then Table1 else Table2 end
我不想用2 select
聲明然而做到這一點。
我可以使用CASE
聲明嗎?
我有2個表格。從兩個表中選擇一個
讓我們打電話給他們Table1
和Table2
。兩個表具有相同的結構和數據類型。
Table1
是交易表,Table2
是歷史數據表。
我需要做這樣的事情:
Select * from case when 'transnational' then Table1 else Table2 end
我不想用2 select
聲明然而做到這一點。
我可以使用CASE
聲明嗎?
偉大的問題!讓我們嘗試:
Create Table tab0 (col int primary key);
Create Table tab1 (col int primary key);
Insert Into tab0 (col) Values (0);
Insert Into tab1 (col) Values (1);
GO
極簡主義聯盟所有的解決方案是:
Declare @tabindex bit = 0;
Select * From tab0 Where @tabindex = 1 Union All
Select * From tab1 Where @tabindex = 0;
執行計劃表示兩個表掃描和過濾器與一個串聯。
這不夠好。讓我們來看看優化是否能夠真正跳過表處理,如果條件不正確:
Select * From tab0 Where 1 = 1 Union All
Select * From tab1 Where 1 = 0
GO
...和執行計劃表示在成本0%一個表掃描和一個計算標量。所以,技術上優化器可以做到這一點。問題是涉及變量的任何條件都會根據表進行評估,從而導致表掃描。所以我們只需要在Select
之前評估狀況。那麼,有一個問題的答案也被表值函數的名字:
Create Function tab (@tabNo int)
Returns @RetTab Table (col int)
As
Begin
If @tabNo = 1 Insert Into @RetTab Select * From tab1
Else Insert Into @RetTab Select * From tab0;
Return;
End;
現在,如果我們運行Select * From tab(1);
或Select * From tab(0);
執行計劃將表明只有一個表掃描,一個表值函數和一個序列兩者都花費0%。
所以答案是是的,我們可以在表值函數中使用CASE
語句。
更新以下Shnugo評論。該功能可以實際加以改進:
Create Function tab (@tabNo int)
Returns Table
As
Return
Select * From tab0 Where @tabNo = 0 Union All
Select * From tab1 Where @tabNo = 1;
GO
現在Select * From tab(1);
或Select * From tab(0);
導致一個表掃描和一個計算標量而已。顯然,使用編譯函數時,優化器不知道在表中查找參數變量。
這需要進一步的測試...BEGIN和END的TVF以其可怕的表現而聞名。比動態Sql更好(可用於ad-hoc),但在大多數現實世界的場景中可能不如UNION ALL快。無論如何值得upvote – Shnugo
@Shnugo感謝您的提示! –
有沒有辦法做到這一點。你可以創建一個視圖聯合兩個表,然後查詢該視圖 – Squirrel
你可以使用'UNION ALL':'SELECT * FROM table1 WHERE @param ='transnational'UNION ALL SELECT * FROM table1 WHERE @param <>'跨國' –
只是提到它:您也可能會考慮動態SQL,但您不能在像VIEW或JOIN這樣的臨時方法中使用它。我的方法是帶有過濾器的'UNION ALL' ... – Shnugo