给出一个结构表:
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)表示。
答案 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
。