【问题标题】:Mysql group by where delta between records XMysql group by where delta between records X
【发布时间】:2015-04-14 13:24:28
【问题描述】:

我需要帮助来编写 MySQL 查询。

我有一个满是日志的表,其中一列是 unix 时间戳。 我想对这些记录进行分组(GROUP BY),以便在它们之间的近距离时间(即 5 秒)内发生的事件属于一个组。

例如:

表:

timestamp
----------
1429016966
1429016964
1429016963
1429016960
1429016958
1429016957
1429016950
1429016949
1429016943
1429016941
1429016940
1429016938

加入这样的团体:

GROUP_CONCAT(timestamp)                                            | COUNT(*)
----------------------------------------------------------------------------- 
1429016966,1429016964,1429016963,1429016960,1429016958,1429016957  |    6
1429016950,1429016949                                              |    2                         
1429016943,1429016941,1429016940,1429016938                        |    4

当然我可以在 php 中处理数据数组,但我认为 mysql 会更快。

【问题讨论】:

  • 堆栈溢出不是代码编写服务。到目前为止,您尝试过什么?
  • 我会尝试解决这个问题,但我已经给出了类似的答案here,这可能对您有所帮助。
  • 我知道不是。我已经搜索了几个小时,但我发现最好的是按时间间隔分组,即 10 分钟、1 小时等,其中时间戳除以 600、3600。
  • 我不认为你的组是正确的,因为第一组跨越 9 秒,而不是 5 秒。
  • 那么问题是组必须包含项目,其中每个项目之间的差异不能大于即 5 秒。整个小组可以是 1 分钟、10 分钟或其他时间。如果差异超过 5 秒,则应创建下一个组。

标签: php mysql group-by delta


【解决方案1】:

我首先使用一个变量来获取每一行的位置,其中 1 是最高的时间列,以最低的时间列结束,如下所示:

SET @a := 0;

SELECT timeCol, @a := @a + 1 AS position
FROM myTable
ORDER BY timeCol DESC;

为简单起见,我们将其命名为positionsTable,以便查询的其余部分更具可读性。创建该表后,我使用了一个“time_group”变量来检查前一行是否在最后 5 秒内。如果是,我们保持相同的 time_group。听起来很丑,看起来也很丑,但它是这样的:

SELECT m.timeCol, m.position,
  CASE WHEN (SELECT p.timeCol FROM positionsTable p WHERE p.position = m.position - 1) <= m.timeCol + 5 
    THEN @time_group 
    ELSE @time_group := @time_group + 1 END AS timeGroup
FROM positionsTable m;

最终,您可以将其用作子查询,将它们分组:

SELECT GROUP_CONCAT(timeCol), COUNT(*)
FROM(
  SELECT m.timeCol, m.position,
    CASE WHEN (SELECT p.timeCol FROM positionsTable p WHERE p.position = m.position - 1) <= m.timeCol + 5 
    THEN @time_group 
    ELSE @time_group := @time_group + 1 END AS timeGroup
  FROM positionsTable m) tmp
GROUP BY timeGroup;

这是一个SQL Fiddle 示例。

【讨论】:

    【解决方案2】:

    http://sqlfiddle.com/#!9/37d88/20

    SELECT GROUP_CONCAT(t1.t) as `time`,
         COUNT(*)
      FROM (SELECT * 
            FROM  table1 
            ORDER BY t) as t1
    GROUP BY CASE WHEN (@start+5)>=t THEN @start 
       ELSE @start:=t END 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-30
      相关资源
      最近更新 更多