我把它放在一张桌子上:
id dateFrom hours
1 2013-02-01 6
2 2013-04-01 8
hours
表示从该日期开始的一个月内的小时数,有效期至下一条记录。
我需要知道如何在两个日期之间总结月份的小时数。
例如,如果范围日期为 2013-02-01 ,则 2013-06-01 :< / p>
6hs for february +
6hs for march +
8hs for april +
8hs for may +
8hs for june
========
36 hs
答案 0 :(得分:4)
DECLARE @startDate DATE
DECLARE @endDate DATE
SET @startDate = '20130201'
SET @endDate = '20130601'
;WITH CTE_Months AS
(
SELECT @startDate DT
UNION ALL
SELECT DATEADD(MM,1,DT) FROM CTE_Months
WHERE DATEADD(MM,1,DT) <= @endDate
)
,CTE_RN AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY DT ORDER BY dateFrom DESC) RN
FROM CTE_Months m
LEFT JOIN Table1 t ON m.DT >= t.dateFrom
)
SELECT SUM(hours)
FROM CTE_RN WHERE RN = 1
第一个递归CTE是在两个日期之间找到差距,在实际表格中使用ROW_NUMBER
和JOIN
查找第二个CTE,以查找每个月的小时数。最后,只需加上WHERE RN=1
<强> SQLFiddle DEMO 强>
答案 1 :(得分:1)
所以这个问题实际上是两个问题。首先,我们需要对其进行规范化,以便我们得到实际的月,小时的元组。我们需要在第n行和第n + 1行之间创建月增量,并为它们分别提供原始表的小时值。
我通过使用可以调用或交叉应用参数的内联表值函数来解决它。
完整的测试解决方案:http://sqlfiddle.com/#!6/b7e58/1
该功能的示例代码以及如何调用它:
CREATE FUNCTION dbo.GetSum(@startDate date,@endDate date)
RETURNS TABLE
AS RETURN
(
WITH cte as
(
SELECT @startDate as s
UNION ALL
SELECT DATEADD(month,1,s)
FROM cte WHERE s<@endDate
)
SELECT
SUM(hours) as sumHours
FROM cte
CROSS APPLY (SELECT top 1 h.hours FROM dbo.hourInterval as h WHERE h.startdate <= cte.s order by h.startdate desc) as t
)
GO
SELECT * FROM dbo.GetSum('2013-02-01','2013-06-01')
答案 2 :(得分:1)
我明白了。 hours
表示从该日期开始的一个月内的小时数。然后,您希望按月添加内容。
以下使用递归CTE计算每个月的一天。然后它连接到您的表,并选择当前行之前的最新行。最后,它累计了几个小时:
declare @fromdate date = '2013-02-01';
declare @todate date = '2013-06-01';
with months as (
select @fromdate as thedate
union all
select DATEADD(month, 1, thedate)
from months
where DATEADD(month, 1, thedate) <= @todate
),
t as (
select 1 as id, CAST('2013-02-01' as DATE) as datefrom, 6 as hours union all
select 2, '2013-04-01', 8
)
select SUM(hours)
from (select t.*, m.thedate, ROW_NUMBER() over (partition by m.thedate order by t.datefrom desc) as seqnum
from months m join
t
on m.thedate >= t.datefrom
) t
where seqnum = 1;