在 MySQL 5.7 中对“孤岛”进行分组

Posted

技术标签:

【中文标题】在 MySQL 5.7 中对“孤岛”进行分组【英文标题】:Grouping 'islands' in MySQL 5.7 【发布时间】:2021-01-22 14:58:56 【问题描述】:

我正在努力解决一个我认为很简单的“差距和孤岛”问题。

转这个结果集:

7:18    WORK
7:19    WORK
7:20    WORK
7:29    BREAK
7:30    BREAK
7:31    WORK
7:32    WORK
7:33    IDLE
7:34    IDLE
7:35    IDLE
7:36    IDLE

到这里:

from_timestamp  until_timestamp status  records_in_island
7:18    7:24    WORK    6
7:29    7:32    BREAK   3
7:31    7:32    WORK    2
7:33    7:36    IDLE    4

或者基本上是展示:

每个岛屿的开始和结束的时间戳 每个岛的记录数

这是一个包含数据的 dbfiddle: https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=a15cc8325ef4bc743df3208f8f328b9a

我在找到的间隙和孤岛解决方案中找不到任何解决方案。我使用的是 MySQL 5.7(由于 AWS Aurora 限制),所以不能使用 WITH 或其他 MySQL 8.0 语法。

任何帮助将不胜感激。

【问题讨论】:

为什么期望输出中第二行的第一列是 7:27,不应该是 7:29 吗? 谢谢 Harsh - 你是 100% 正确的 - 我在创建 dbfiddle 时注意到了这个错误。感谢您的关注。 【参考方案1】:

另一种方法是在SELECT 语句中使用变量:

SELECT event, MIN(event_time) AS event_time, COUNT(*) AS cnt
FROM (
  SELECT 
    CASE WHEN @e = event THEN @c ELSE @c := @c + 1 END AS id,
    event_time,  @e := event AS event
  FROM events, (SELECT @c := 0, @e := '') vars
  ORDER BY event_time
) t  
GROUP BY id, event
ORDER BY event_time

fiddle

但由于 MySQL 8 在表达式中设置用户变量已被弃用,并将在未来的版本中删除。

【讨论】:

User14717238 - 你太棒了。 我相信您的工作很愉快,但如果您正在考虑新的机会,请告诉我们。如果您发送电子邮件至jobs@getclue.com,我会直接收到。 PS 你优雅的解决方案效果很好。【参考方案2】:

也许最简单的方法是使用where 过滤掉“先前”值与第 2 列的值相同的值。假设这些值是日期/时间值并且恰好在一分钟内对齐:

select t.*
from (select t.*,
             (select t2.status
              from test t2
              where t2.timestamp < t.timestamp
              order by t2.timestamp desc
              limit 1
             ) as prev_status
      from test t
     ) t
where not prev_status <=> status;

Here 是一个 dbfiddle。

【讨论】:

谢谢戈德隆。我刚刚编辑了问题并添加了一个 db fiddle,因为我无法使您的查询正常工作。这是小提琴:dbfiddle.uk/… @Clueless 。 . .我修复了小提琴,因此时间戳是唯一的,修改了查询以对应您的数据模型,并将小提琴添加到答案中。

以上是关于在 MySQL 5.7 中对“孤岛”进行分组的主要内容,如果未能解决你的问题,请参考以下文章

如何对连续范围进行分组(mysql 5.7)

在 MySQL 中对重叠的数据范围进行分组

如何在 MySQL 中对具有不同平均值的三个变量进行分组?

MySQL 5.7 - 分组不工作

浅析MySQL使用 GROUP BY 分组聚合与细分聚合

mysql5.7 group by语法 1055