2012-02-07 98 views
3

给定结构的表格:查找期间(月)范围内涵盖的年份百分比?

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] 

与数据

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) 

假设我们提供在例如@StartPeriod = 201009周期(即2010年3月被表示为201003)的日期范围,@EndPeriod = 201108

我将如何查询表Example,以便获取日期范围内涵盖的时间段的代表性数据。

与上面给出的日期范围的情况下,我们会得到:

(.33333*25) + (.66666*30) = 26.66666 

哪里.33333是因为2010只有4个在期间日期范围代表个月(占全年的1/3),和.66666是因为2011年有8个月(全年的2/3)在日期范围内表示。

如何编写查询以获得那些具有代表性的“权重”?还假定在某些情况下日期范围可以跨越多年,即@StartPeriod = 200905,@EndPeriod = 201104,在这种情况下,2010将由100%(1)表示。

回答

3

您可以构建一个CTE中所有月份的列表。匹配的月份是每年小时数的十二分之一。您可以使用inner join加起来只有匹配月:

; 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) 

结果是4/12*20+8/12*30 = 26.66。您的示例答案是21.66,因为它使用20作为2011年的小时数。该答案是使用每个数据集的30

Working example at SE Data.

+0

太棒了。谢谢Andomar。感谢您指出我的错误:2011年的价值 - 修正了。不知道data.stackexchange.com。绝对不可思议! – richard 2012-02-07 10:04:56