从两个表中的任何一个中选择

时间:2016-04-26 06:57:01

标签: sql-server

我有2张桌子。

让我们称呼他们Table1Table2。两个表都具有相同的结构和数据类型。

Table1是一个交易表,Table2是一个历史数据表。

我需要做这样的事情:

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

但我不想使用2 select语句来执行此操作。

我可以使用CASE语句吗?

1 个答案:

答案 0 :(得分: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);只会产生一个表扫描和一个计算标量。显然,对于编译函数,优化器知道不要在表中查找参数变量。