Skip to content
Advertisement

Select max data in interval of 1 hour within a time range in sql

I have some difficulties with sql server to select max value in a column in interval of 1 hour within a time range.

My table look like this:

+----------+-------+---------------------+
|    Id    | Value |      TimeStamp      |
+----------+-------+---------------------+
| 02030105 | 32.20 | 2019-04-21 08:21:50 |
| 02030106 | 30.00 | 2019-04-21 08:36:40 |
| 02030107 | 30.50 | 2019-04-21 08:51:10 |
| 02030108 | 27.70 | 2019-04-21 09:31:23 |
| 02030201 | 32.20 | 2019-04-21 09:50:30 |
| 02030202 | 32.00 | 2019-04-22 10:19:50 |
| 02030203 | 31.70 | 2019-04-22 10:34:26 |
| 02030204 | 31.00 | 2019-04-22 11:33:04 |
| 02030205 | 31.20 | 2019-04-22 11:47:50 |
+----------+-------+---------------------+

How do I select max Value column in interval of 1 hour within a time range from 2019-04-21 08:21:50 to 2019-04-22 11:47:50

I want my output to be like this:

+----------+-------+---------------------+
|    Id    | Value |      TimeStamp      |
+----------+-------+---------------------+
| 02030105 | 32.20 | 2019-04-21 08:21:50 |
| 02030201 | 32.20 | 2019-04-21 09:50:30 |
| 02030202 | 32.00 | 2019-04-22 10:19:50 |
| 02030205 | 31.20 | 2019-04-22 11:47:50 |
+----------+-------+---------------------+

Advertisement

Answer

You can use ROW_NUMBER() in a subquery to assign a rank to each record withing groups of each records having the same timestamp (minutes and seconds excluded) ordered by value, and then filter on the top record in each group in the outer query:

SELECT id, value, timestamp
FROM (
    SELECT 
        t.*,
        ROW_NUMBER() OVER(
            PARTITION BY dateadd(hour, datediff(hour, 0, timestamp), 0) 
            ORDER BY value DESC
        ) rn
    FROM mytable t
) x WHERE rn = 1

Demo on DB Fiddle:

     id | value | timestamp          
------: | :---- | :------------------
2030105 | 32.20 | 2019-04-21 08:21:50
2030201 | 32.20 | 2019-04-21 09:50:30
2030202 | 32.00 | 2019-04-22 10:19:50
2030205 | 31.20 | 2019-04-22 11:47:50

If you want the average value within each 1h range as well, then:

SELECT id, value, timestamp, avg_value
FROM (
    SELECT 
        t.*,
        ROW_NUMBER() OVER(
            PARTITION BY dateadd(hour, datediff(hour, 0, timestamp), 0) 
            ORDER BY value DESC
        ) rn,
        AVG(value) OVER(
            PARTITION BY dateadd(hour, datediff(hour, 0, timestamp), 0) 
        ) avg_value
    FROM mytable t
) x WHERE rn = 1
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement