2012-02-07 95 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