Reputation: 1031
I have following query that I want to improve so it displays two additional columns as Variance
and Percentage_Variance
.
declare @w0s datetime
declare @w0e datetime
declare @w1s datetime
declare @w1e datetime
set @w0s = dateadd(hh, datediff(hh, 0, getdate()), 0)
set @w0e = getdate()
set @w1s = dateadd(dd, datediff(dd, 0, getdate()) / 7 * 7 - 7, 0)
set @w1e = dateadd(dd, datediff(dd, 0, getdate()) / 7 * 7, 0)
select
state,
sum(case
when create_time >= @w0s and create_time < @w0e
then 1 else 0
end) as Call_Volume_This_hr,
sum(case
when create_time >= @w1s and create_time < @w1e
then 1 else 0
end) / 7.0 as Avg_Call_Volume_Past_Week1
--,(case when ((sum(case when create_time>=@w0s and create_time<@w0e then 1 else 0 end)) - (sum(case when create_time>=@w1s and create_time<@w1e then 1 else 0 end)/7.0) > 0)then 1 else 0 end) as Variance
--,(case when (((case when ((sum(case when create_time>=@w0s and create_time<@w0e then 1 else 0 end)) - (sum(case when create_time>=@w1s and create_time<@w1e then 1 else 0 end)/7.0) > 0)then 1 else 0 end)/(sum(case when create_time>=@w1s and create_time<@w1e then 1 else 0 end)/7.0)*100.0) > 0) then 1 else 0 end) as Percentage_Variance
from
ctirpts.dbo.cti_reporting
where
create_time >= @w1s
and datepart(hh, create_time) = datepart(hour, getdate())
and state is not null
group by
state
;
The condition is that
if (Call_Volume_This_hr > Avg_Call_Volume_Past_Week1)
then
Variance = Call_Volume_This_hr - Avg_Call_Volume_Past_Week1
and
Percentage_Variance = (Variance/Avg_Call_Volume_Past_Week1)*100
else
Variance = 0 and Percentage_Variance = 0
The two commented lines shows my feeble attempt at getting this done but it prints 1 under columns "Variance" and "Percentage_Variance" when "if (Call_Volume_This_hr > Avg_Call_Volume_Past_Week1)" is true. Instead I want the actual computed values as per:
Variance = Call_Volume_This_hr - Avg_Call_Volume_Past_Week1
Percentage_Variance = (Variance/Avg_Call_Volume_Past_Week1)*100
I would appreciate any help or pointers.
Upvotes: 0
Views: 54
Reputation: 980
You could put your initial select into a common table expression, then those calculated SUM columns become much more readily available for conditional computation. You can use an APPLY operator to perform the CASE statement, returning Variance of zero or more (never negatives). Then you can perform the calculation to get the percentage variance.
-- this CTE performs the initial aggregation and makes the recordset available
-- to be used like a table:
;with PreAggregate
as (
select state
,sum(case when create_time>=@w0s and create_time<@w0e then 1 else 0 end) as Call_Volume_This_hr
,sum(case when create_time>=@w1s and create_time<@w1e then 1 else 0 end)/7.0 as Avg_Call_Volume_Past_Week1
from ctirpts.dbo.cti_reporting
where create_time>=@w1s
and datepart(hh,create_time)=datepart(hour, getdate())
and state is not null
group by state
)
-- The APPLY operator creates an inline-table-value function without the
-- "black box" query optimizer problems of using an actual UDF
-- The "CROSS APPLY" calculates a 0 or more value for Variance.
-- The Variance value can then be used to compute Percentage_Variance.
select PreAggregate.state
, PreAggregate.Call_Volume_This_hr
, PreAggregate.Avg_Call_Volume_Past_Week1
, InlineFunction.Variance
, (InlineFunction.Variance/PreAggregate.Avg_Call_Volume_Past_Week1)*100 as 'Percentage_Variance'
from PreAggregate
cross apply (
select case
when Call_Volume_This_hr < Avg_Call_Volume_Past_Week1 then 0
else Call_Volume_This_hr -Avg_Call_Volume_Past_Week1
end 'Variance'
) InlineFunction;
Upvotes: 1
Reputation: 2052
I think your two commented lines should be as follows:
( ( SUM(CASE WHEN create_time >= @w0s
AND create_time < @w0e THEN 1
ELSE 0
END) ) - ( SUM(CASE WHEN create_time >= @w1s
AND create_time < @w1e THEN 1
ELSE 0
END) / 7.0 ) ) AS Variance,
( ( CASE WHEN ( ( SUM(CASE WHEN create_time >= @w0s
AND create_time < @w0e THEN 1
ELSE 0
END) ) - ( SUM(CASE WHEN create_time >= @w1s
AND create_time < @w1e THEN 1
ELSE 0
END) / 7.0 ) > 0 ) THEN 1
ELSE 0
END ) / ( SUM(CASE WHEN create_time >= @w1s
AND create_time < @w1e THEN 1
ELSE 0
END) / 7.0 ) * 100.0 ) AS Percentage_Variance
However without a fiddle or some structure and data I was unable to test it beyond correct syntax. Essentially the outermost CASE statements where the problem. They needed to be removed.
Upvotes: 0