Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional UNION ALL in table function

So use case is as follows - there're some parameter, based on which I want to select data from one table or another.

create table dbo.TEST1 (id int primary key, name nvarchar(128))
create table dbo.TEST2 (id int primary key, name nvarchar(128))

So I've created function like this:

create function [dbo].[f_TEST]
(
    @test bit
)
returns table
as
return (
    select id, name from TEST1 where @test = 1

    union all

    select id, name from TEST2 where @test = 0
)

When I run it with constant, the execution plan is great - only one table is scanned

select * from dbo.f_TEST(1)

enter image description here

But, then, when I use variable, plan is not that good - both tables are scanned

declare @test bit = 1

select * from dbo.f_TEST(@test)

enter image description here

So are there any hints (or tricks) to force SQL Server to understand that in a certain query only one table should be scanned?

like image 797
Roman Pekar Avatar asked Aug 15 '17 18:08

Roman Pekar


2 Answers

If your function is inline-TVP(as in example) then you could use:

declare @test bit = 1
select * from dbo.f_TEST(@test) OPTION (RECOMPILE);

Then in both cases you will get single clustered index scan.

DBFiddle Demo

From Option RECOMPILE:

When compiling query plans, the RECOMPILE query hint uses the current values of any local variables in the query and, if the query is inside a stored procedure, the current values passed to any parameters.

like image 157
Lukasz Szozda Avatar answered Sep 18 '22 20:09

Lukasz Szozda


It works fine as is. Take a look at "Number of Executions" on the relevant table, as you change your parameter value. The tables that will be excluded appear in the plan, because they must be considered, but that does not mean they will be scanned.

Number of Executions: 0

Also, look at the Startup Expression on the Filter:

enter image description here

like image 36
Pittsburgh DBA Avatar answered Sep 19 '22 20:09

Pittsburgh DBA