2016-04-26 121 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感谢您的提示! –