Reputation: 12526
Given a table of structure:
CREATE TABLE [dbo].[Example](
[FiscalYear] INT NOT NULL,
[Hours] [decimal](28, 2) NULL,
CONSTRAINT [PK_Example] PRIMARY KEY CLUSTERED (
[FiscalYear] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
with data
INSERT INTO [Example] ([FiscalYear], [Hours]) VALUES (2009 ,25) GO
INSERT INTO [Example] ([FiscalYear], [Hours]) VALUES (2010 ,20) GO
INSERT INTO [Example] ([FiscalYear], [Hours]) VALUES (2011 ,30)
Assuming we provide a date range in periods (i.e. March 2010 is expressed as 201003) for instance @StartPeriod = 201009
, @EndPeriod = 201108
How would I query table Example
so that I get representative data for the periods covered in the date range.
In the case with the date range given above, we would get:
(.33333*25) + (.66666*30) = 26.66666
Where .33333
is because 2010 has only 4 months (1/3 of the total year) represented in the period date range, and .66666
is because 2011 has 8 months (2/3 of the total year) represented in the period date range.
How do I write a query to get those representative "weights"? Also assume that in some cases a date range could span multiple years i.e. @StartPeriod = 200905
, @EndPeriod = 201104
in which case 2010 would be represented by 100% (1).
Upvotes: 3
Views: 476
Reputation: 238246
You can build a list of all months in a CTE. Matching months contribute 1/12th of the yearly number of hours. You can use an inner join
to add up only the matching months:
; with AllMonths as
(
select cast('2001-01-01' as datetime) as MonthStart
union all
select dateadd(month, 1, MonthStart)
from AllMonths
where MonthStart < '2020-01-01'
)
select sum(e.Hours/12)
from AllMonths am
join @example e
on e.FiscalYear = datepart(year, am.MonthStart)
where am.MonthStart between '2010-09-01' and '2011-08-01'
option (maxrecursion 0)
The result is 4/12*20+8/12*30 = 26.66
. Your example answer was 21.66
because it uses 20
as the number of hours for 2011. THis answer is using 30
per the dataset.
Upvotes: 3