I have a simple database table (Postgres) consisting of 3 attributes (f1,f2 and f3) ordered by date. (db<>fiddle).
I want to transform (group?) the result into the following table:
| f1 | f2 | f3 | beginn | end |
|---|---|---|---|---|
| A | A | A | 31.12.2017 | 05.01.2018 |
| B | B | B | 06.01.2018 | 10.01.2018 |
| A | A | A | 11.01.2018 | 16.01.2018 |
I tried (but obviously failed) with:
SELECT a.f1 ,a.f2 ,a.f3 ,MIN(datum) AS beginn ,MAX(datum) AS end FROM test1 a GROUP BY 1,2,3
I tried a bit with window-functions but that wasn’t leading to anywhere.
Do you have any ideas how I can get to the desired result?
Advertisement
Answer
If you enumerate the rows for each combination of f1, f2, and f3, then subtract that number of days from datum, then the value will be constant on adjacent days where the three columns are the same.
The rest is just aggregation:
select f1, f2, f3, min(datum), max(datum)
from (select t1.*,
row_number() over (partition by f1, f2, f3 order by datum) as seqnum
from test1 t1
) t1
group by f1, f2, f3, datum - seqnum * interval '1 day'
order by min(datum);
Here is a db<>fiddle.