检查范围是否重叠
Check if ranges are overlapping
我有一个 table 这样的:
Id min_val max_val
1 5 7
2 8 12
3 4 6
如果 min_val 和 max_val 与任何其他 ID 重叠,我想得到 True/False。所以,结果如下:
Id result
1 True
2 False
3 True
谢谢。
一种方法使用 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;
另一种方法使用 window 函数。如果月经可以同时开始就有点棘手了,但是思路是:
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;
这可能有点矫枉过正,但您可以使用 JOIN,如下所示,不仅可以了解是否存在重叠,还可以了解重叠的内容:
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
;
如果您将共享边界算作重叠,只需将 >
和 <
分别更改为 >=
和 <=
。
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
我有一个 table 这样的:
Id min_val max_val
1 5 7
2 8 12
3 4 6
如果 min_val 和 max_val 与任何其他 ID 重叠,我想得到 True/False。所以,结果如下:
Id result
1 True
2 False
3 True
谢谢。
一种方法使用 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;
另一种方法使用 window 函数。如果月经可以同时开始就有点棘手了,但是思路是:
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;
这可能有点矫枉过正,但您可以使用 JOIN,如下所示,不仅可以了解是否存在重叠,还可以了解重叠的内容:
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
;
如果您将共享边界算作重叠,只需将 >
和 <
分别更改为 >=
和 <=
。
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