MySQL 根据某些条件对一列 Select 第二列值进行排序

MySQL Sort One Column Select 2nd Column Values Based on some Criteria

我有一个 table 与下面的非常相似。我需要将 end_time 排序为升序,然后 select start_time 表示在 selected end_time 的正负 2 秒内剩余的行。从本质上讲,我想做的是创建一个端到端的链 end_times 匹配开始时间的端到端。

因此,在第一次匹配后,我将获得匹配的 start_time 行的 main_id 并重复其 end_time。使用这个你可以看到从下面的 table 可以找到以下链接或聚合。

1->2
3->4
5->6->7->8
10->11

现在我可以很容易地通过读取行​​以编程方式完成此操作,例如 PHP,但想知道在 SQL 中是否有更有效的方法来执行此操作,其中一些tables 可能很大。

+-------------------+------------+
|main_id|start_time |   end_time |
|-------------------+------------+
| 1      1467695616   1467695676 |
| 2      1467695677   1467695683 |
| 3      1467782122   1467782182 |
| 4      1467782181   1467782238 |
| 5      1472329347   1472329374 |
| 6      1472329375   1472329553 |
| 7      1472329554   1472329733 |
| 8      1472329734   1472329764 |
| 9      1472329949   1472330078 |
|10      1472330275   1472330453 |
|11      1472330454   1472330479 |
+----+--------------+------------+

在第一个示例中,我们为每一行分配了一个组。如果前一个 end_time 和当前行 start_time 之间的差异在 +/- 2 秒内,我们将保持相同的组号,否则我们增加组号。这应该适用于 MySQL.
的所有版本 在第二个示例中,我们使用 windows 函数 lag() over (order by ~)sum(~) over(order by ~) 和 CTE,因此它在 MySQL 低于 8.

的版本中不起作用
create table t (
main_id int,
start_time int,
end_time int);
insert into t values
(1,1467695616,1467695676),
(2,1467695677,1467695683),
(3,1467782122,1467782182),
(4,1467782181,1467782238),
(5,1472329347,1472329374),
(6,1472329375,1472329553),
(7,1472329554,1472329733),
(8,1472329734,1472329764),
(9,1472329949,1472330078),
(10,1472330275,1472330453),
(11,1472330454,1472330479);
set @latest  = 0;
set @group = 0;
select
@group  := case when abs(start_time - @latest) <= 2
                   then @group
                   else @group + 1 
                   end  "group",
main_id, 
start_time,
@latest := end_time "end_time"
from t 
order by end_time,start_time
> group | main_id | start_time |   end_time
> ----- | --------| -----------| -----------|
>     1 |       1 | 1467695616 | 1467695676
>     1 |       2 | 1467695677 | 1467695683
>     2 |       3 | 1467782122 | 1467782182
>     2 |       4 | 1467782181 | 1467782238
>     3 |       5 | 1472329347 | 1472329374
>     3 |       6 | 1472329375 | 1472329553
>     3 |       7 | 1472329554 | 1472329733
>     3 |       8 | 1472329734 | 1472329764
>     4 |       9 | 1472329949 | 1472330078
>     5 |      10 | 1472330275 | 1472330453
>     5 |      11 | 1472330454 | 1472330479
> 
with CTE as
(select
case when abs(start_time - lag(end_time) over(order by end_time, start_time)) > 2 then 1 else 0 end  diff_previous,
main_id, 
start_time,
end_time
from t 
order by end_time,start_time
)
select
1 + sum(diff_previous) over(order by end_time) as "group",
main_id, 
start_time,
end_time
from CTE
order by end_time, start_time
group | main_id | start_time |   end_time
----: | ------: | ---------: | ---------:
    1 |       1 | 1467695616 | 1467695676
    1 |       2 | 1467695677 | 1467695683
    2 |       3 | 1467782122 | 1467782182
    2 |       4 | 1467782181 | 1467782238
    3 |       5 | 1472329347 | 1472329374
    3 |       6 | 1472329375 | 1472329553
    3 |       7 | 1472329554 | 1472329733
    3 |       8 | 1472329734 | 1472329764
    4 |       9 | 1472329949 | 1472330078
    5 |      10 | 1472330275 | 1472330453
    5 |      11 | 1472330454 | 1472330479

db<>fiddle here