Home > Net >  In SQL, how to split timestamps into several intervals but with the first record of the day as the b
In SQL, how to split timestamps into several intervals but with the first record of the day as the b

Time:03-08

PostgreSQL 9.5

My dataset looks like this: Sample data


I want to split the records of the same day into a 1-minute interval, but with the beginning of each interval as the min value of the interval.

With this dataset, my ideal output would look like this: Output

For example, in 2014-05-27, the min value is 15:09:40, so the first one-minute interval would be 15:09:40 - 15:10:40, and there're three records. For the next interval, 15:11:01 - 15:12:01, there's one record.

Hope I have made myself clear. Thanks in advance.

CodePudding user response:

You can try to use CTE or subquery to get a gap_seconds which represents a value from subtracting of occurred_at and previous occurred_at of row, then making an grp column to calculate values that hold the gap.

;WITH CTE AS (
    SELECT *,
           FLOOR(SUM(gap_seconds) OVER(ORDER BY occurred_at) / 60) grp
    FROM (
        SELECT *,
               EXTRACT(SECOND FROM  occurred_at - LAG(occurred_at,1,occurred_at) OVER(ORDER BY occurred_at)) gap_seconds
        FROM T
    ) t1
)
SELECT MIN(occurred_at) occurred_at,
       COUNT(*)
FROM CTE
GROUP BY grp
ORDER BY 1

sqlfiddle

another example, we can division by 120 second like this below query

WITH CTE AS (
    SELECT *,
           FLOOR(SUM(gap_seconds) OVER(ORDER BY occurred_at) / 120) grp
    FROM (
        SELECT *,
               EXTRACT(SECOND FROM  occurred_at - LAG(occurred_at,1,occurred_at) OVER(ORDER BY occurred_at)) gap_seconds
        FROM T
    ) t1
)
SELECT MIN(occurred_at) occurred_at,
       COUNT(*)
FROM CTE
GROUP BY grp
ORDER BY 1

sqlfiddle

  • Related