2016-04-26 170 views
3

我有2個表格。從兩個表中選擇一個

讓我們打電話給他們Table1Table2。兩個表具有相同的結構和數據類型。

Table1是交易表,Table2是歷史數據表。

我需要做這樣的事情:

Select * from case when 'transnational' then Table1 else Table2 end 

我不想用2 select聲明然而做到這一點。

我可以使用CASE聲明嗎?

+2

有沒有辦法做到這一點。你可以創建一個視圖聯合兩個表,然後查詢該視圖 – Squirrel

+2

你可以使用'UNION ALL':'SELECT * FROM table1 WHERE @param ='transnational'UNION ALL SELECT * FROM table1 WHERE @param <>'跨國' –

+1

只是提到它:您也可能會考慮動態SQL,但您不能在像VIEW或JOIN這樣的臨時方法中使用它。我的方法是帶有過濾器的'UNION ALL' ... – Shnugo

回答

2

偉大的問題!讓我們嘗試:

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);導致一個表掃描和一個計算標量而已。顯然,使用編譯函數時,優化器不知道在表中查找參數變量。

+1

這需要進一步的測試...BEGIN和END的TVF以其可怕的表現而聞名。比動態Sql更好(可用於ad-hoc),但在大多數現實世界的場景中可能不如UNION ALL快。無論如何值得upvote – Shnugo

+0

@Shnugo感謝您的提示! –