I have a table looking like this:
GR | I | VON | BIS |
---|---|---|---|
1 | a | 1 | 2 |
2 | b | 2 | 3 |
1 | c | 3 | 4 |
1 | d | 4 | 5 |
3 | e | 5 | 6 |
Column “GR” is the info I want to use for grouping.
Column “I” holds some none important info.
Column “VON” holds originally a date value – for readability I used a number here.
The same goes for column “BIS”.
So the records hold some information that is valid for the interval which is specified by “VON” and “BIS” and should be grouped by “GR”.
I’m trying to build a query to get the result like this:
GR | I | VON | BIS |
---|---|---|---|
1 | a | 1 | 2 |
2 | b | 2 | 3 |
1 | c | 3 | 5 |
3 | e | 5 | 6 |
That means, I want to merge rows with the same grouping information – in the example by merging records 3 and 4.
What I came up with was this query – but this only works for distinct groups:
select distinct gr ,first_value(i) over(partition by gr order by von asc) i ,first_value(von) over(partition by gr order by von asc) von ,first_value(bis) over(partition by gr order by von desc) bis from table_test ;
With our test data it leads to this result, which is obviously wrong:
GR | I | VON | BIS |
---|---|---|---|
1 | a | 1 | 5 |
2 | b | 2 | 3 |
3 | e | 5 | 6 |
Any ideas how to solve this with a query? (I know I could do it with PL/SQL, but it needs to be pure SQL …)
Advertisement
Answer
From Oracle 12, you can use MATCH_RECOGNIZE
to perform row-by-row processing:
SELECT * FROM table_test MATCH_RECOGNIZE( ORDER BY von MEASURES FIRST(gr) AS gr, FIRST(i) AS i, FIRST(von) AS von, LAST(bis) AS bis PATTERN (same_gr+) DEFINE same_gr AS FIRST(gr) = gr )
Which, for your sample data:
CREATE TABLE table_test (GR, I, VON, BIS) AS SELECT 1, 'a', 1, 2 FROM DUAL UNION ALL SELECT 2, 'b', 2, 3 FROM DUAL UNION ALL SELECT 1, 'c', 3, 4 FROM DUAL UNION ALL SELECT 1, 'd', 4, 5 FROM DUAL UNION ALL SELECT 3, 'e', 5, 6 FROM DUAL;
Outputs:
GR I VON BIS 1 a 1 2 2 b 2 3 1 c 3 5 3 e 5 6
db<>fiddle here