I’m trying to select pairs of events from my data. I have a data that looks like this:
create table test(id,status,created)as values
(1, 'on','2024-09-01'::date)
,(2, 'on','2024-09-02'::date)
,(1,'off','2024-09-03'::date)
,(1, 'on','2024-09-04'::date)
,(2,'off','2024-09-05'::date)
,(3, 'on','2024-09-06'::date)
,(1,'off','2024-09-07'::date)
,(4,'off','2024-09-08'::date);
I would like to have data like this:
| id | switched_on | switched_off |
|---|---|---|
| 1 | 2024-09-01 | 2024-09-03 |
| 1 | 2024-09-04 | 2024-09-07 |
| 2 | 2024-09-02 | 2024-09-05 |
| 3 | 2024-09-06 | |
| 4 | 2024-09-08 |
I am interested in:
- multiple events for the same
idin the data nullvalues when either end of event pair is missing
>Solution :
An example using the self-join:
- Match on
id - Make sure the left table is for earlier
onevents, right for lateroff. - This matches every
onevent with all lateroffs for eachid. Adistinct onkeeps only a single match for eachidandonevent, selecting the soonestoff.
select distinct on (1,2)
coalesce(t1.id,t2.id)
,t1.created as switched_on
,t2.created as switched_off
from test as t1
full join test as t2
on t1.id=t2.id
and t1.created<t2.created
where coalesce(t1.status,'on')='on'
and coalesce(t2.status,'off')='off'
order by 1,2, t2.created-t1.created;
| coalesce | switched_on | switched_off |
|---|---|---|
| 1 | 2024-09-01 | 2024-09-03 |
| 1 | 2024-09-04 | 2024-09-07 |
| 2 | 2024-09-02 | 2024-09-05 |
| 3 | 2024-09-06 | null |
| 4 | null | 2024-09-08 |