Как описано в принятом ответе, решение состоит в том, чтобы объединить перекрывающиеся диапазоны вместе, а затем определить, присутствует ли тестовый диапазон в одном из объединенных диапазонов.
Помимо объединения и / или рекурсии, вы можете использовать метод сортировки с оконными функциями для объединения перекрывающихся диапазонов:
WITH ranges(id, a, b) AS (
SELECT 1, 0, 40 UNION
SELECT 2, 40, 60 UNION
SELECT 3, 80, 100 UNION
SELECT 4, 10, 30
), tests(id, a, b) AS (
SELECT 1, 10, 90 UNION
SELECT 2, 10, 60
), ranges_chg AS (
SELECT *, CASE WHEN MAX(b) OVER (ORDER BY a ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) >= a THEN 0 ELSE 1 END AS chg
FROM ranges
), ranges_grp AS(
SELECT *, SUM(chg) OVER (ORDER BY a) AS grp
FROM ranges_chg
), merged_ranges AS (
SELECT MIN(a) AS a, MAX(b) AS b
FROM ranges_grp
GROUP BY grp
)
SELECT *
FROM tests
WHERE EXISTS (
SELECT 1
FROM merged_ranges
WHERE merged_ranges.a <= tests.a AND tests.b <= merged_ranges.b
)
Результат и Скрипка .
| id | a | b |
|----|----|----|
| 2 | 10 | 60 |
Данные внутри range_grp
CTE даст вам представление о том, как это работает:
| id | a | b | max b over... | chg | grp |
|----|----|-----|---------------|-----|-----|
| 1 | 0 | 40 | NULL | 1 | 1 |
| 4 | 10 | 30 | 40 | 0 | 1 |
| 2 | 40 | 60 | 40 | 0 | 1 |
| 3 | 80 | 100 | 60 | 1 | 2 |