MySQL - 类似时间戳的组

时间:2010-07-15 18:01:08

标签: mysql group-by aggregate-functions

查询:

  SELECT project_id, 
         COUNT(*) AS count,
         MIN(date_added) AS date_start, 
         MAX(date_added) AS date_end
    FROM my_table 
GROUP BY project_id, TIMESTAMPDIFF(MINUTE, date_added) < 5
WHERE user_id = 1 LIMIT 10

我怎样才能做到这一点?我想对项目进行分组,以便组中没有两个连续项目相隔超过5分钟,但开始和结束时间可以相隔任何距离。有没有办法在数据库中执行此操作,或者我是否需要获取所有数据并在程序中找到它?

3 个答案:

答案 0 :(得分:3)

好的,这里有:

SELECT id, project_id, start_time, MAX(end_time) AS end_time FROM (
  SELECT
    @new_group :=
      ((TIME_TO_SEC(date_added) - @prev_second) > (5 * 60)) ||
      (project_id <> @prev_project_id) AS new_group,
    @date_added_group := @date_added_group + @new_group AS date_added_group,
    @start_time := IF(@new_group, date_added, @start_time) AS start_time,
    id,
    project_id,
    date_added AS end_time,
    @prev_second := TIME_TO_SEC(date_added) AS prev_sec,
    @prev_project_id := project_id AS prev_project
  FROM my_table,
  (SELECT
    @new_group :=0,
    @date_added_group := 0,
    @start_time := 0,
    @prev_second := 0,
    @prev_project_id := 0) AS vars
  ORDER BY project_id, date_added
) AS my_table GROUP BY project_id, date_added_group;

鉴于此数据:

+----+------------+---------------------+
| id | project_id | date_added          |
+----+------------+---------------------+
|  1 |          1 | 2010-07-15 19:00:00 | < new project
|  2 |          1 | 2010-07-15 19:01:00 |
|  3 |          1 | 2010-07-15 19:02:00 |
|  4 |          2 | 2010-07-15 19:03:00 | < new project
|  5 |          2 | 2010-07-15 19:04:00 |
|  6 |          2 | 2010-07-15 19:25:00 | < new interval
|  7 |          2 | 2010-07-15 19:26:00 |
|  8 |          2 | 2010-07-15 19:27:00 |
|  9 |          2 | 2010-07-15 19:48:00 | < new interval
| 10 |          2 | 2010-07-15 19:49:00 |
| 11 |          3 | 2010-07-15 19:50:00 |
| 12 |          3 | 2010-07-15 20:11:00 | < new interval
| 13 |          4 | 2010-07-15 20:12:00 | < new project
| 14 |          4 | 2010-07-15 20:13:00 |
| 15 |          4 | 2010-07-15 20:14:00 |
| 16 |          5 | 2010-07-15 20:15:00 | < new project
| 17 |          5 | 2010-07-15 20:16:00 |
| 18 |          5 | 2010-07-15 21:27:00 | < new interval
| 19 |          5 | 2010-07-15 21:28:00 |
| 20 |          6 | 2010-07-15 21:29:00 | < new project
| 21 |          6 | 2010-07-15 21:30:00 |
| 22 |          6 | 2010-07-15 21:31:00 |
+----+------------+---------------------+

查询返回此结果集:

+----+------------+---------------------+---------------------+
| id | project_id | start_time          | end_time            |
+----+------------+---------------------+---------------------+
|  1 |          1 | 2010-07-15 19:00:00 | 2010-07-15 19:02:00 | 
|  4 |          2 | 2010-07-15 19:03:00 | 2010-07-15 19:04:00 |
|  6 |          2 | 2010-07-15 19:25:00 | 2010-07-15 19:27:00 |
|  9 |          2 | 2010-07-15 19:48:00 | 2010-07-15 19:49:00 |
| 11 |          3 | 2010-07-15 19:50:00 | 2010-07-15 19:50:00 |
| 12 |          3 | 2010-07-15 20:11:00 | 2010-07-15 20:11:00 |
| 13 |          4 | 2010-07-15 20:12:00 | 2010-07-15 20:14:00 |
| 16 |          5 | 2010-07-15 20:15:00 | 2010-07-15 20:16:00 |
| 18 |          5 | 2010-07-15 21:27:00 | 2010-07-15 21:28:00 |
| 20 |          6 | 2010-07-15 21:29:00 | 2010-07-15 21:31:00 |
+----+------------+---------------------+---------------------+

答案 1 :(得分:2)

在我的头顶,我没有尝试:

  SELECT project_id, 
         COUNT(*) AS count,
         MIN(date_added) AS date_start, 
         MAX(date_added) AS date_end
    FROM my_table 
   WHERE user_id = 1 
GROUP BY project_id, ROUND(date_added / (5 * 60))
   LIMIT 10

当然,假设在几秒钟内“注明日期”。

换句话说,项目根据它们所属的5分钟切片进行分组。

答案 2 :(得分:0)

由于您希望将最长的记录链连接在一起,每对记录的间距小于5分钟,我认为您无法使用GROUP BY执行此操作。

尝试使用WHILE loop编写存储过程。从一个选择记录ORDER BY date_added的游标开始。您可以创建TEMPORARY TABLE并在每个组的末尾插入一行。通过将其作为存储过程,您可以避免将所有记录拉回到您的程序中(通常通过网络),这可以使它更快。