I would like to find out if I have overlapping time slices that have the same id and the same name. In the following example, the entries with id=2 and name=c overlaps. Entry with id=1 is just for demonstration of a good case.
Given table:
x
+---+------+-------+------------+--------------+
|id | name | value | validFrom | validTo |
+---+------+-------+------------+--------------+
|1 | a | 12 | 2019-01-01 | 9999-12-31 |
|1 | b | 34 | 2019-01-01 | 2019-10-31 |
|1 | b | 35 | 2019-11-01 | 9999-12-31 |
|1 | c | 13 | 2019-01-01 | 2025-12-31 |
|2 | a | 49 | 2019-01-01 | 9999-12-31 |
|2 | b | 99 | 2019-01-01 | 2034-12-31 |
|2 | c | 75 | 2019-01-01 | 2019-10-31 |
|2 | c | 84 | 2019-10-28 | 9999-12-31 |
|n | | | | |
+---+------+-------+------------+--------------+
expected output:
+---+------+
|id | name |
+---+------+
|2 | c |
+---+------+
Thanks for your help in advance!
Advertisement
Answer
You can get the overlapping rows using exists
:
select t.*
from t
where exists (select 1
from t t2
where t2.id = t.id and
t2.name = t.name and
t2.value <> t.value and
t2.validTo > t.validFrom and
t2.validFrom < t.validTo
);
If you just want the id
/name
combinations:
select distinct t.id, t.name
from t
where exists (select 1
from t t2
where t2.id = t.id and
t2.name = t.name and
t2.value <> t.value and
t2.validTo > t.validFrom and
t2.validFrom < t.validTo
);
You can also do this with a cumulative max:
select t.*
from (select t.*,
max(validTo) over (partition by id, name
order by validFrom
rows between unbounded preceding and 1 preceding
) as prev_validTo
from t
) t
where prev_validTo >= validFrom;