Home > database >  SQL Server Difference of Aggregate Window
SQL Server Difference of Aggregate Window

Time:11-10

I want to fetch some data (energy consumption) from an SQL Server table by creating a window of 5 mins and finding its aggregate.

The SQL Table stores some telemetry data captured every minute. Now what I have to do is, calculate the difference of values of (T 5 mins) and T, for all the windows.

I tried to use the aggregate window but was not able to get the intended results.

Are there any T-SQL functionalities that I can utilize to get such output without running a loop (Want to avoid this as it would be a non-optimal solution)?

An example of my scenario is mentioned below.

Timestamp Energy_Value
2021-11-09T01:01:00.000Z 100
2021-11-09T01:02:00.000Z 102
2021-11-09T01:03:00.000Z 103
2021-11-09T01:04:00.000Z 105
2021-11-09T01:05:00.000Z 107
2021-11-09T01:06:00.000Z 108
2021-11-09T01:07:00.000Z 120
2021-11-09T01:08:00.000Z 123
2021-11-09T01:09:00.000Z 128
2021-11-09T01:10:00.000Z 135

Needs to be converted to (Timestamps have been converted for simplicity and brackets are provided for explanation of calculation)

Agg_Timestamp Agg_Energy_Value
01:01:00 - 01:05:00 7 (107-100)
01:01:05 - 01:09:00 21 (128-107)

CodePudding user response:

Although it's fully inline with your example, it will work only if you have every minute without seconds and so on and so forth.

take a look, please

create table #t
(
     ts datetime2
    ,val int
)

insert into #t
values
 ('2021-11-09T01:01:00.000Z', 100)
,('2021-11-09T01:02:00.000Z', 102)
,('2021-11-09T01:03:00.000Z', 103)
,('2021-11-09T01:04:00.000Z', 105)
,('2021-11-09T01:05:00.000Z', 107)
,('2021-11-09T01:06:00.000Z', 108)
,('2021-11-09T01:07:00.000Z', 120)
,('2021-11-09T01:08:00.000Z', 123)
,('2021-11-09T01:09:00.000Z', 128)
,('2021-11-09T01:10:00.000Z', 135)

select  format(ts, 'hh:mm:ss')   ' - '   format(next_ts, 'hh:mm:ss')
        ,cast(next_val - val as varchar(10))   ' ('   cast(next_val as varchar(10))   ' - '   cast(val as varchar(10))   ')'
from
    (
        select   ts
                ,val
                ,lead(ts) over(order by ts) as next_ts
                ,lead(val) over(order by ts) as next_val
        from
            (
                select *, (row_number() over(order by ts) - 1) % 4 as row_id
                from #t
            ) SQ
        where row_id = 0
    ) SQ
where next_ts is not null

CodePudding user response:

To aggregate them in windows of 5 minutes?
Then this may be as simple as also grouping by the minutes divided by 12.

SELECT 
 CONCAT(CONVERT(VARCHAR, MIN(t.[Timestamp]), 108), ' - ', CONVERT(VARCHAR, MAX(t.[Timestamp]), 108)) AS Agg_Timestamp,
 CONCAT(MAX(t.Energy_Value)-MIN(t.Energy_Value), ' (', MAX(t.Energy_Value), '-', MIN(t.Energy_Value), ')' ) AS Agg_Energy_Value
FROM yourtable t
GROUP BY CAST(t.[Timestamp] AS DATE),
  DATEPART(hour, t.[Timestamp]),
  ROUND((DATEPART(minute, t.[Timestamp])/12.0), 0)

Result:

Agg_Timestamp       | Agg_Energy_Value
:------------------ | :---------------
01:01:00 - 01:05:00 | 7 (107-100)     
01:06:00 - 01:10:00 | 27 (135-108)    
  • Related