Skip to content
Advertisement

How to find overlapping time slices of serveral key-value elements

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:

+---+------+-------+------------+--------------+
|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;
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement