I am having problems figuring out why a query is taking drastically longer to run based on me swapping out a parameter against a real value.
DECLARE @quarter int
DECLARE @year int
DECLARE @countOfUnitsBought int
set @year = 2009
set @quarter = 1
set @countOfUnitsBought = 4;
with res
as
(
select
o.account_id
--,orderyear
--,orderquarter
from
fmtables.[dbo].[orders] o
--cross apply(values(year(o.[ship_date]))) as a1(orderyear)
--cross apply(values(DatePart(quarter,(o.[ship_date])))) as a2(orderquarter)
where
ship_date = (select min(ship_date) from fmtables.[dbo].[orders] mo where [account_id] = o.account_id) and
total_value > 0 AND
order_status NOT LIKE 'return%' AND
order_status NOT LIKE 'cancel%' AND
order_status NOT LIKE 'freeze%' and
CAST(DatePart(quarter,(o.[ship_date])) as int) = @quarter and
year(o.[ship_date]) = @year and
(select sum(quantity) from fmtables..[orders] ox inner join fmtables..[orderlines] olx on ox.order_id = olx.order_id
where olx.order_id = o.order_id and [product_code] in(select [product_code] from fmtables..[products] where [category_code] in('1','2','3','4'))) >= @countOfUnitsBought
)
select * from res;
This query takes 43 seconds to run.
Now if I simply replace the @quarter and change to a literal
CAST(DatePart(quarter,(o.[ship_date])) as int) = 1 and
it now takes 1 second.
Can anyone please give me a clue as to why and if I need to change some casting to help. Thanks Scott
EDIT:
So I manage to get it whizzing through with the help of everyone's comments. I used a mix of passing the parameters from the inputs and then through to a 'local' variable inside the procedure.
alter procedure [dbo].[Lifetime_HeadsetUnits]
@inquarter int , @inyear int, @incountOfUnitsBought int
as
DECLARE @quarter int
DECLARE @year int
declare @countOfUnitsBought int
select @quarter = @inquarter
select @year = @inyear
select @countOfUnitsBought = @incountOfUnitsBought
and also the
OPTION (OPTIMIZE FOR(@quarter = 1))
as part of the final output query.
OPTION (OPTIMIZE FOR(@quarter = 1))