我有2张桌子。
让我们称呼他们Table1
和Table2
。两个表都具有相同的结构和数据类型。
Table1
是一个交易表,Table2
是一个历史数据表。
我需要做这样的事情:
Select * from case when 'transnational' then Table1 else Table2 end
但我不想使用2 select
语句来执行此操作。
我可以使用CASE
语句吗?
答案 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
语句。
更新。实际上可以改进这个功能:
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);
只会产生一个表扫描和一个计算标量。显然,对于编译函数,优化器知道不要在表中查找参数变量。