Проверьте, перекрываются ли диапазоны - PullRequest
0 голосов
/ 25 февраля 2020

У меня есть такая таблица:

Id  min_val  max_val
1   5        7
2   8        12
3   4        6

Я хочу получить True / False, если min_val и max_val перекрываются с любым другим идентификатором. Итак, результат, как показано ниже:

Id result
1  True  
2  False 
3  True

Спасибо.

Ответы [ 3 ]

2 голосов
/ 25 февраля 2020

Один метод использует exists:

select t.*,
       (exists (select 1
                from t t2
                where t2.id <> t.id and
                      t2.max_val > t.min_val and
                      t2.min_val < t.max_val
               )
       ) as result;
from t;

Другой метод использует оконные функции. Немного сложнее, если периоды могут начинаться одновременно, но идея такова:

select t.*,
       (max(max_val) over (order by min_val range between unbounded preceding and 1 preceding) > min_val) or
        min(min_val) over (order by max_val desc range between unbounded preceding and current row)
       ) as result
from t;
1 голос
/ 25 февраля 2020

Это может быть излишним, но вы можете использовать JOINs, как показано ниже, чтобы не только знать, есть ли перекрытие, но и что перекрывается:

SELECT t.id, tOther.id As overlappingId
FROM t
LEFT JOIN t AS tOther 
   ON t.id <> tOther.id            -- Not the same record
   AND t.min_val < tOther.max_val  -- Starts before "other" ends
   AND t.max_val > tOther.min_val  -- Ends after "other" starts
;

Если вам нужна только одна строка результата на t, запрос можно настроить с агрегацией.

SELECT t.id
    , COUNT(tOther.id) AS overlappingCount      -- Count ignores null values
    , GROUP_CONCAT(tOther.id) AS overlappingIDs -- Will be null if no overlaps
FROM t
LEFT JOIN t AS tOther 
   ON t.id <> tOther.id            -- Not the same record
   AND t.min_val < tOther.max_val  -- Starts before "other" ends
   AND t.max_val > tOther.min_val  -- Ends after "other" starts
GROUP BY t.id
;

Если вы считаете общую границу перекрывающейся, просто измените > и < на >= и <= соответственно.

0 голосов
/ 26 февраля 2020
SELECT t2.id, 

CASE WHEN t2.id IN
(SELECT DISTINCT t.id
FROM tab1 as t
LEFT JOIN tab1 AS t1
WHERE t.id <> t1.id AND (t.min_val < t1.max_val AND t.max_val > t.min_val)) 
THEN "True" ELSE "False" END AS Results

FROM tab1 as t2

Это работает для меня. Спасибо @Uueerdo и @Gordon Linoff

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...