问题
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