Mysql 按记录 X 之间的增量分组
Mysql group by where delta between records X
我需要帮助来编写 MySQL 查询。
我有 table 满满的日志,其中一列是 unix 时间戳。
我想对这些记录进行分组(GROUP BY),以便在它们之间的近距离时间(即 5 秒)内发生的事件属于一组。
例如:
Table:
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 会更快。
我首先使用一个变量来获取每一行的位置,其中 1 是最高时间列,以最低时间列结束,如下所示:
SET @a := 0;
SELECT timeCol, @a := @a + 1 AS position
FROM myTable
ORDER BY timeCol DESC;
为简单起见,我们将其称为positionsTable
,以便查询的其余部分更具可读性。创建 table 后,我使用 '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 示例。
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
我需要帮助来编写 MySQL 查询。
我有 table 满满的日志,其中一列是 unix 时间戳。 我想对这些记录进行分组(GROUP BY),以便在它们之间的近距离时间(即 5 秒)内发生的事件属于一组。
例如:
Table:
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 会更快。
我首先使用一个变量来获取每一行的位置,其中 1 是最高时间列,以最低时间列结束,如下所示:
SET @a := 0;
SELECT timeCol, @a := @a + 1 AS position
FROM myTable
ORDER BY timeCol DESC;
为简单起见,我们将其称为positionsTable
,以便查询的其余部分更具可读性。创建 table 后,我使用 '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 示例。
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