我有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