2015-08-31 41 views
1

我有一系列独特的事件,可能会持续任意时间。由于事件可能会在特定的月份之前开始(在这种情况下,它会贡献上个月以及当前的月份)并且在特定的月份之后完成,所以我需要计算事件对每月总计的贡献小时数。查询跨越月份边界的事件的月总时数

的数据看起来类似:

Event | StartDate | EndDate | 
------------------------------- 
| 1 | 10/01/2015| 11/01/2015| 
| 2 | 20/12/2014| 9/01/2015 | 
| 3 | 25/01/2015| 14/02/2015| 

最后,我尝试生成按月和年份合计每个月的“事件时间”(而不是每个事件分组名单 - 一个月内事件总结)。

说实话,我甚至不知道从哪里开始。

+0

你的日期字段是'date'或'datetime'?因为如果你现在想要计算小时数,全部都是24h –

+0

这里的结束日期没有意义。这是虚拟价值吗?结束日期应该大于开始日期 活动开始日期结束日期 | 2 | 20/12/2015 | 9/01/2015 | –

+0

我的错误 - 我会纠正它 – skyman

回答

1

简单的方法是使用月表,因为你可以有空的月份。

create table months (
    month_id integer, 
    date_ini datetime, 
    date_end datetime 
) 

然后你做一个加入你的表。

SQL Fiddle Demo

WITH ranges as (
    SELECT * 
    FROM 
     months m 
     LEFT JOIN events e 
      on e.StartDate <= m.d_end 
      and e.EndDate >= m.d_begin 
) 
SELECT r.*, 
     DATEDIFF(hour, 
       CASE 
        WHEN StartDate > d_begin THEN StartDate 
        WHEN StartDate IS NULL THEN NULL 
        ELSE d_begin 
       END, 
       CASE 
        WHEN EndDate < d_end THEN EndDate 
        WHEN EndDate IS NULL THEN NULL 
        ELSE DATEADD(day,1,d_end) 
       END) as Hours 
FROM ranges r 

你有4案件

  • 一个事件,其中的开始和结束都是一个月
  • 一个事件,其中到底是超出月末
  • 一个事件开始内前后一个月结束
  • 一个月没有事件。
+0

不知道我明白 - 你的意思是以这样一种方式将一个月表加入到事件表中,使得联合是事件列表(可能与跨越国界的事件重复)和时间他们在每个月内消费? – skyman

+0

我刚刚通过它......在第二排活动2将于20日开始,并在31日(第一张唱片)结束,然后在1日开始,并在下个月的9日结束 – skyman

+0

我认为它可能需要CASE开关来设置月份中断或IF然后? – skyman

0

尝试。这将工作。

WITH EventInfo AS 
(
    SELECT EVENT, DATEDIFF(HOUR, StartDate,EndDate) AS hours, 
     DATEPART(MONTH, EndDate) AS Month, 
     DATEPART(Year, EndDate) AS Year 
    FROM events 
) 
SELECT Month, Year, SUM(hours) AS Total_hours 
FROM EventInfo 
Group By Month, Year 

这里是SQLFiddle

+0

谢谢 - 也会尝试这个以及 – skyman

+0

我不认为这会考虑到您可能只能计算一个月内的事件的一部分? – skyman