I am using Postgresql 13 and I have a table that looks something like this:
event_id | timestamp |
---|---|
1 | 2022-11-28 00:00:00 |
1 | 2022-11-28 00:00:10 |
2 | 2022-11-28 00:00:20 |
2 | 2022-11-28 00:00:30 |
2 | 2022-11-28 00:00:40 |
3 | 2022-11-28 00:00:50 |
3 | 2022-11-28 00:01:10 |
1 | 2022-11-28 00:01:20 |
2 | 2022-11-28 00:01:30 |
2 | 2022-11-28 00:01:40 |
3 | 2022-11-28 00:01:50 |
3 | 2022-11-28 00:02:10 |
3 | 2022-11-28 00:02:20 |
4 | 2022-11-28 00:02:30 |
I need to get monotonically increasing values for the event_id column based on the timestamp order. So the above table will become something like:
event_id | timestamp |
---|---|
1 | 2022-11-28 00:00:00 |
1 | 2022-11-28 00:00:10 |
2 | 2022-11-28 00:00:20 |
2 | 2022-11-28 00:00:30 |
2 | 2022-11-28 00:00:40 |
3 | 2022-11-28 00:00:50 |
3 | 2022-11-28 00:01:10 |
4 | 2022-11-28 00:01:20 |
5 | 2022-11-28 00:01:30 |
5 | 2022-11-28 00:01:40 |
6 | 2022-11-28 00:01:50 |
6 | 2022-11-28 00:02:10 |
6 | 2022-11-28 00:02:20 |
7 | 2022-11-28 00:02:30 |
Ideally I'd need this done in a single select statement, I tried a bunch of different approaches but nothing led me even close to what I need. Any suggestion? Thanks
CodePudding user response:
You can assign a unique row number to each "chunk" of similar event_id
s:
with cte as (
select (select sum(case when t1.event_id != t.event_id then 1 else 0 end)
from tbl t1 where t1.timestamp <= t.timestamp) k, t.*
from tbl t
)
select t3.r, v.value#>>'{}' from (select row_number() over (order by (
select max(v.value::text) from json_array_elements(t2.js) v)) r, t2.* from (
select t1.event_id, t1.k, json_agg(t1.timestamp) js from cte t1
group by t1.event_id, t1.k) t2) t3
cross join json_array_elements(t3.js) v
CodePudding user response:
Try the following using a running sum of a flag that is set to 1 whenever event_id is changed over the increasing of timestamp.
select sum(flag) over (order by timestamp) 1 as event_id,
timestamp
from
(
select *,
case
when lag(event_id, 1, event_id)
over (order by timestamp) <> event_id
then 1 else 0
end as flag
from table_name
) T
order by timestamp
See a demo.