查找涵盖期间(月)范围的年份百分比?

时间:2012-02-07 07:22:11

标签: sql

给出一个结构表:

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)

假设我们提供期间的日期范围(即2010年3月表示为201003),例如@StartPeriod = 201009@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)表示。

1 个答案:

答案 0 :(得分:3)

您可以在CTE中构建所有月份的列表。匹配月份占每年小时数的1/12。您可以使用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.