Вы хотите объединить свои диапазоны по идентификатору. Допустим, данные для идентификатора 1:
+ ---+-----+------+
| id | Low | High |
+ ---+-----+------+
| 1 | 2 | 7 |
| 1 | 3 | 4 |
| 1 | 7 | 8 |
| 1 | 7 | 10 |
| 1 | 12 | 13 |
| 1 | 13 | 20 |
| 1 | 20 | 24 |
+ ---+-----+------+
. У нас есть два кластера: 2-10, 12-24. Недостаточно взглянуть на еще один ряд, скажем, на предыдущий, чтобы определить, находятся ли они в одном кластере. 3-4 и 7-8 могут показаться не связанными на первый взгляд, но они принадлежат к одному кластеру, поскольку они оба перекрываются с 2-7.
Я вижу итерационный процесс, где мы упорядочиваем строки по ID и Низкий и сохраняем самое высокое значение диапазона при переходе:
+ ---+-----+------+---------+----------------------------------+
| id | Low | High | Highest | Cluster |
+ ---+-----+------+---------+----------------------------------+
| 1 | 2 | 7 | 7 | 1 (start with #1) |
| 1 | 3 | 4 | 7 | 1 (3 <= 7) |
| 1 | 7 | 8 | 8 | 1 (7 <= 7) |
| 1 | 7 | 10 | 10 | 1 (7 <= 8) |
| 1 | 12 | 13 | 13 | 2 (next number, because 12 > 10) |
| 1 | 13 | 20 | 20 | 2 (13 <= 13) |
| 1 | 20 | 24 | 24 | 2 (20 <= 20 |
+ ---+-----+------+---------+----------------------------------+
Для итеративного процесса нам нужен рекурсивный запрос в SQL:
with recursive numbered as
(
select t.*, row_number() over (partition by id order by low) as rn
from mytable t
)
, cte (id, rn, low, high, highest, tag) as
(
select id, rn, low, high, high, 1 from numbered where rn = 1
union all
select
n.id, n.rn, n.low, n.high,
case when n.low <= c.highest then greatest(n.high, c.highest) else n.high end,
case when n.low <= c.highest then c.tag else c.tag + 1 end
from cte c
join numbered n on n.id = c.id and n.rn = c.rn + 1
)
select id, low, high, tag
from cte
order by id, low, high;
Демо: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=3f38a60cdcbb2711e5fb1d7fd7fefa07