SUM of Duration based on the DateTime that needs to be updated in previous Half hour interval

坚强是说给别人听的谎言 提交于 2019-12-10 12:19:55

问题


I searched several questions but that all are not exactly answering my question. Hence raised this question here. I have a table say 'Table' that has has DateTime,ID, Code and Duration are the columns. DateTime will be having data as '2017-12-12 00:30:00','2017-12-12 00:30:37' etc and I need to SUM the duration column based on this Interval date. If DateTime is '2017-12-12 00:30:00' then our query should sum all the data between '2017-12-12 00:00:00' to '2017-12-12 00:30:00' and show it in '2017-12-12 00:00:00'

Actual table data.

DateTime    ID  Code    Duration
2017-12-12 00:30:00 1   12  1800
2017-12-12 00:30:37 1   12  37
2017-12-12 01:00:00 1   12  1793
2017-12-12 01:30:00 1   12  1800
2017-12-12 01:30:59 1   12  59

If I run the query then expected result is,

DateTime    ID  Code    Duration
2017-12-12 00:00:00 1   12  1800
2017-12-12 00:30:00 1   12  1800
2017-12-12 01:00:00 1   12  1800
2017-12-12 01:30:00 1   12  59

The Query I have with me is below,

      SELECT 
      Interval=(CASE WHEN datepart(MINUTE,[DateTime]) = 0 and datepart(SS,DateTime)=0 THEN
CAST(CONVERT(VARCHAR(30),DATEADD(HOUR,-1,[DateTime]),101) + ' '+ cast(format(DATEPART(HOUR,DATEADD(HOUR,-1,[DateTime])),'0#')
 as varchar)+':30:00' as DateTime)
ELSE (CAST(CONVERT(VARCHAR(30),[DateTime],101) +' ' + (case when datepart(MINUTE,[DateTime])<=30 then cast(format(DATEPART(HOUR,[DateTime]),'0#') as varchar)+':00:00'
      else cast(format(DATEPART(HOUR,[DateTime]),'0#') as varchar)+':30:00' end) as DateTime)) END),    
      ID,Code,Duration=SUM(Duration) FROM Table
      WHERE [DateTime]  >= '2017-12-11 00:00:00'  and [DateTime] <= '2017-12-11 23:59:59' 
        GROUP BY  ID,Code,
      (CASE WHEN datepart(MINUTE,[DateTime]) = 0 and datepart(SS,DateTime)=0 THEN
CAST(CONVERT(VARCHAR(30),DATEADD(HOUR,-1,[DateTime]),101) + ' '+ cast(format(DATEPART(HOUR,DATEADD(HOUR,-1,[DateTime])),'0#') as varchar)+':30:00' as DateTime)
ELSE (CAST(CONVERT(VARCHAR(30),[DateTime],101) +' ' + (case when datepart(MINUTE,[DateTime])<=30 then cast(format(DATEPART(HOUR,[DateTime]),'0#') as varchar)+':00:00'
       else cast(format(DATEPART(HOUR,[DateTime]),'0#') as varchar)+':30:00' end) as DateTime)) END)

The output i'm getting is,

DateTime    ID  Code    Duration
2017-12-12 00:00:00 1   12  1837
2017-12-12 00:30:00 1   12  1793
2017-12-12 01:00:00 1   12  1859

The mistake I have here is, seconds part is not splitting and it is adding to previous interval, instead of next interval. Key point here is we should not get more than 1800 seconds in a 30 minutes interval DateTime.

If you need any more clarifications please let me know I clarify further.


回答1:


Use simple date logic

 GROUP BY  DATEADD( MINUTE
    , ( DATEDIFF( MINUTE, [DateTime], '2017-12-12') / 30 )  * 30
    , '2017-12-12')

This divides the DateTime column (you should never use keywords as column names) into 30 minute segments from the seed value, discarding any remainders. Then it multiplies by 30 again to get to the number of minutes duration from the seed value for the bucket. Finally it adds the minutes to the seed value to create the datetime bucket.

Note that the seed date value doesn't matter, but the seed time value will make a difference because you want the buckets aligned to the half hour. Using midnight is the cleanest approach.



来源:https://stackoverflow.com/questions/47777427/sum-of-duration-based-on-the-datetime-that-needs-to-be-updated-in-previous-half

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!