snippetsqlMinor
How to get minimum and maximum for grouped timestamps
Viewed 0 times
maximumminimumgetgroupedforhowandtimestamps
Problem
I would love to know how to create a view that groups timestamps in 10 minute nearest 10 minute intervals and contains each minimum and maximum timestamp for each.
So a table that looks like this:
would result in a view like this
or this:
Either solution would be fine.
So a table that looks like this:
| Hero | timestamp |
| Batman | 2016-12-08 12:00:00 |
| Batman | 2016-12-08 12:07:00 |
| Batman | 2016-12-08 13:00:00 |
| Batman | 2016-12-08 14:00:00 |
| Wonder Woman | 2016-12-08 10:15:00 |
| Wonder Woman | 2016-12-08 10:18:00 |
| Wonder Woman | 2016-12-08 10:25:00 |
| Wonder Woman | 2016-12-08 10:30:00 |would result in a view like this
| Hero | start_time | end_time |
| Batman | 2016-12-08 12:00:00 | 2016-12-08 12:07:00 |
| Wonder Woman | 2016-12-08 10:15:00 | 2016-12-08 10:30:00 |or this:
| Hero | start_time | end_time |
| Batman | 2016-12-08 13:00:00 | NULL |
| Batman | 2016-12-08 14:00:00 | NULL |
| Batman | 2016-12-08 12:00:00 | 2016-12-08 12:07:00 |
| Wonder Woman | 2016-12-08 10:15:00 | 2016-12-08 10:30:00|Either solution would be fine.
Solution
Raster of 10-minute intervals
I suggest to group by a combination of "hour" and 10-minute interval:
Refer to the chapter Date/Time Functions and Operators in the manual.
The
I advise not to use the "timestamp" as identifier. It's a reserved word in standard SQL and base data type in Postgres.
Groups defined by gaps of 10 or more minutes
If "groups" are defined by gaps of 10 minutes or more between rows of the same hero:
Detailed explanation:
db<>fiddle here
Old sqlfiddle
I suggest to group by a combination of "hour" and 10-minute interval:
SELECT hero
, min(timestamp) AS start_time
, CASE WHEN count(*) > 1 THEN max(timestamp) END AS end_time
FROM tbl
GROUP BY hero
, date_trunc('hour', timestamp)
, EXTRACT(MINUTE FROM timestamp)::int / 10
ORDER BY 1, 2; -- optionalRefer to the chapter Date/Time Functions and Operators in the manual.
EXTRACT(minute FROM timestamp) extracts the minute part of the time The expression. After the cast to integer (::int), integer division (/ 10) effectively rounds to 10-minute intervals (0 - 5).The
CASE expression only adds an end_time if more than one rows fall in the same 10-minute interval.I advise not to use the "timestamp" as identifier. It's a reserved word in standard SQL and base data type in Postgres.
Groups defined by gaps of 10 or more minutes
If "groups" are defined by gaps of 10 minutes or more between rows of the same hero:
SELECT hero
, count(*) AS ct -- optional
, min(timestamp) AS start_time
, CASE WHEN count(*) > 1 THEN max(timestamp) END AS end_time
FROM (
SELECT hero, timestamp, count(step OR NULL) OVER (ORDER BY hero, timestamp) AS grp
FROM (
SELECT *
, lag(timestamp) OVER (PARTITION BY hero ORDER BY timestamp)
< timestamp - interval '10 min' AS step
FROM tbl
) sub1
) sub2
GROUP BY hero, grp;Detailed explanation:
- Select longest continuous sequence
db<>fiddle here
Old sqlfiddle
Code Snippets
SELECT hero
, min(timestamp) AS start_time
, CASE WHEN count(*) > 1 THEN max(timestamp) END AS end_time
FROM tbl
GROUP BY hero
, date_trunc('hour', timestamp)
, EXTRACT(MINUTE FROM timestamp)::int / 10
ORDER BY 1, 2; -- optionalSELECT hero
, count(*) AS ct -- optional
, min(timestamp) AS start_time
, CASE WHEN count(*) > 1 THEN max(timestamp) END AS end_time
FROM (
SELECT hero, timestamp, count(step OR NULL) OVER (ORDER BY hero, timestamp) AS grp
FROM (
SELECT *
, lag(timestamp) OVER (PARTITION BY hero ORDER BY timestamp)
< timestamp - interval '10 min' AS step
FROM tbl
) sub1
) sub2
GROUP BY hero, grp;Context
StackExchange Database Administrators Q#157595, answer score: 5
Revisions (0)
No revisions yet.