mysql - 将多行中的日期聚合为一行

标签 mysql date group-by aggregate

我有一张表,用于存储事件(如摇滚音乐会)的 GPS 坐标。

看起来像这样:

sequence | event_id | location_id | device_number |         timestamp       | latitude  |  longitude  | event
--------------------------------------------------------------------------------------------------------------------------------
   1     |   101    |   2201      |      220      |     2013-10-29 05:01:00 | 37.757196 | -122.441681 | enter
   2     |   101    |   2202      |      220      |     2013-10-29 05:02:00 | 37.757196 | -122.441681 | NULL
   3     |   101    |   2203      |      220      |     2013-10-29 05:03:00 | 37.757196 | -122.441681 | NULL
   4     |   101    |   2204      |      220      |     2013-10-29 05:04:00 | 37.757196 | -122.441681 | NULL
   5     |   101    |   2205      |      220      |     2013-10-29 05:05:00 | 37.757196 | -122.441681 | NULL
   6     |   101    |   2206      |      220      |     2013-10-29 05:06:00 | 37.757196 | -122.441681 | NULL
   7     |   101    |   2207      |      220      |     2013-10-29 05:07:00 | 37.757196 | -122.441681 | exit
   8     |   102    |   2208      |      220      |     2013-10-29 05:08:00 | 38.865221 | -123.920201 | enter
   9     |   102    |   2209      |      220      |     2013-10-29 05:09:00 | 38.865221 | -123.920201 | NULL
  10     |   102    |   2210      |      220      |     2013-10-29 05:10:00 | 38.865221 | -123.920201 | NULL
  11     |   102    |   2211      |      220      |     2013-10-29 05:11:00 | 38.865221 | -123.920201 | NULL
  12     |   102    |   2212      |      220      |     2013-10-29 05:12:00 | 38.865221 | -123.920201 | NULL
  13     |   102    |   2213      |      220      |     2013-10-29 05:13:00 | 38.865221 | -123.920201 | NULL
  14     |   102    |   2214      |      220      |     2013-10-29 05:14:00 | 38.865221 | -123.920201 | exit
  15     |   101    |   2215      |      220      |     2013-10-29 05:15:00 | 37.757196 | -122.441681 | enter
  16     |   101    |   2216      |      220      |     2013-10-29 05:16:00 | 37.757196 | -122.441681 | NULL
  17     |   101    |   2217      |      220      |     2013-10-29 05:17:00 | 37.757196 | -122.441681 | NULL
  18     |   101    |   2218      |      220      |     2013-10-29 05:18:00 | 37.757196 | -122.441681 | NULL
  19     |   101    |   2219      |      220      |     2013-10-29 05:19:00 | 37.757196 | -122.441681 | NULL
  20     |   101    |   2220      |      220      |     2013-10-29 05:20:00 | 37.757196 | -122.441681 | NULL
  21     |   101    |   2221      |      220      |     2013-10-29 05:21:00 | 37.757196 | -122.441681 | exit
  22     |   101    |   2222      |      330      |     2013-10-29 05:15:00 | 37.757197 | -122.441682 | enter
  23     |   101    |   2223      |      330      |     2013-10-29 05:16:00 | 37.757197 | -122.441682 | NULL
  24     |   101    |   2224      |      330      |     2013-10-29 05:17:00 | 37.757197 | -122.441682 | NULL
  25     |   101    |   2225      |      330      |     2013-10-29 05:18:00 | 37.757197 | -122.441682 | NULL
  26     |   101    |   2226      |      330      |     2013-10-29 05:19:00 | 37.757197 | -122.441682 | NULL
  27     |   101    |   2227      |      330      |     2013-10-29 05:20:00 | 37.757197 | -122.441682 | exit
  • device_number 是用户拥有的特定 GPS 设备。
  • event 列指示特定 GPS device_number 何时根据其地理坐标走进或走出 event_id。

我想在名为billable_times 的表中总结上述数据:

id | event_id | device_number |    begin_time       |     end_time        | duration (minutes)
----------------------------------------------------------------------------------------------
1  |   101    |     220       | 2013-10-29 05:01:00 | 2013-10-29 05:07:00 |    6
2  |   102    |     220       | 2013-10-29 05:08:00 | 2013-10-29 05:14:00 |    6
3  |   101    |     220       | 2013-10-29 05:15:00 | 2013-10-29 05:21:00 |    6
4  |   101    |     330       | 2013-10-29 05:15:00 | 2013-10-29 05:20:00 |    5

如何将一系列时间戳存储为仅包含 begin_timeend_time 的一行?

以下是一些有用的表创建脚本:

CREATE TABLE `intersections` (
  `sequence` int(11) NOT NULL AUTO_INCREMENT,
  `event_id` int(11) DEFAULT NULL,
  `location_id` int(11) NOT NULL,
  `device_number` varchar(255) NOT NULL,
  `timestamp` datetime NOT NULL,
  `latitude` decimal(20,15) NOT NULL,
  `longitude` decimal(20,15) NOT NULL,
  `event` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`sequence`),
  UNIQUE KEY `index_intersections_on_location_id_and_event_id` (`location_id`,`event_id`)
);


INSERT INTO `intersections` (`sequence`, `event_id`, `location_id`, `device_number`, `timestamp`, `latitude`, `longitude`, `event`)
VALUES
  (1,  101, 2201, '220', '2013-10-29 05:01:00', 37.757196, -122.441681, 'enter'),
  (2,  101, 2202, '220', '2013-10-29 05:02:00', 37.757196, -122.441681, NULL),
  (3,  101, 2203, '220', '2013-10-29 05:03:00', 37.757196, -122.441681, NULL),
  (4,  101, 2204, '220', '2013-10-29 05:04:00', 37.757196, -122.441681, NULL),
  (5,  101, 2205, '220', '2013-10-29 05:05:00', 37.757196, -122.441681, NULL),
  (6,  101, 2206, '220', '2013-10-29 05:06:00', 37.757196, -122.441681, NULL),
  (7,  101, 2207, '220', '2013-10-29 05:07:00', 37.757196, -122.441681, 'exit'),

  (8,  102, 2208, '220', '2013-10-29 05:08:00', 37.757196, -122.441681, 'enter'),
  (9,  102, 2209, '220', '2013-10-29 05:09:00', 37.757196, -122.441681, NULL),
  (10, 102, 2210, '220', '2013-10-29 05:10:00', 37.757196, -122.441681, NULL),
  (11, 102, 2211, '220', '2013-10-29 05:11:00', 37.757196, -122.441681, NULL),
  (12, 102, 2212, '220', '2013-10-29 05:12:00', 37.757196, -122.441681, NULL),
  (13, 102, 2213, '220', '2013-10-29 05:13:00', 37.757196, -122.441681, NULL),
  (14, 102, 2214, '220', '2013-10-29 05:14:00', 37.757196, -122.441681, 'exit'),

  (15, 101, 2215, '220', '2013-10-29 05:15:00', 37.757196, -122.441681, 'enter'),
  (16, 101, 2216, '220', '2013-10-29 05:16:00', 37.757196, -122.441681, NULL),
  (17, 101, 2217, '220', '2013-10-29 05:17:00', 37.757196, -122.441681, NULL),
  (18, 101, 2218, '220', '2013-10-29 05:18:00', 37.757196, -122.441681, NULL),
  (19, 101, 2219, '220', '2013-10-29 05:19:00', 37.757196, -122.441681, NULL),
  (20, 101, 2220, '220', '2013-10-29 05:20:00', 37.757196, -122.441681, NULL),
  (21, 101, 2221, '220', '2013-10-29 05:21:00', 37.757196, -122.441681, 'exit'),

  (22, 101, 2222, '330', '2013-10-29 05:15:00', 37.757196, -122.441681, 'enter'),
  (23, 101, 2223, '330', '2013-10-29 05:16:00', 37.757196, -122.441681, NULL),
  (24, 101, 2224, '330', '2013-10-29 05:17:00', 37.757196, -122.441681, NULL),
  (25, 101, 2225, '330', '2013-10-29 05:18:00', 37.757196, -122.441681, NULL),
  (26, 101, 2226, '330', '2013-10-29 05:19:00', 37.757196, -122.441681, NULL),
  (27, 101, 2227, '330', '2013-10-29 05:20:00', 37.757196, -122.441681, 'exit');

CREATE TABLE `billable_times` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `event_id` int(11) DEFAULT NULL,
  `device_number` varchar(255) DEFAULT NULL,
  `begin_time` datetime DEFAULT NULL,
  `end_time` datetime DEFAULT NULL,
  `duration` float DEFAULT NULL,
  PRIMARY KEY (`id`)
);

我正在使用 MySQL,但任何 SQL 风格都可以接受。 (我会尝试将其翻译成 MySQL :)。

最佳答案

试试这个

insert into billable_times

SELECT event_id, device_number, 
min(timestamp) begin,
max(timestamp) end,
sum(dura) duration from 
(
SELECT sequence, event_id, device_number, timestamp, 
if(@id <> concat(event_id,device_number), 0, 
                  TIMESTAMPDIFF(MINUTE,@prev, timestamp)) dura, 
@rank := if(@id <> concat(event_id,device_number),  @rank + 1, @rank) rn,
@prev :=  timestamp, @id := concat(event_id,device_number)
from intersections, (Select @diff := 0, @id := null, @prev := null, @rank :=1) r
) v group by event_id, device_number, rn
order by rn;

select * from billable_times;

SQL FIDDLE

关于mysql - 将多行中的日期聚合为一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20250527/

相关文章:

python - Pandas groupby 并与其他数据框求和

python - 将组上的顺序计数器列添加到 pandas 数据帧

mysql - 如何知道mysql中的列何时创建?

mysql - SQL - 多对多替代方案?

date - 给定 ISO 8601 周数,在 LibreOffice Calc 电子表格中获取该周第一天的日期

php - 优化 mysql 日期生成器?

java - 将信用卡日期 MM/yy 格式化为 MM/dd/yyyy

sql - 计算子组中的记录数,同时保留组中的许多记录

java - 错误记录器和验证身份验证java

mysql - 如何使用 "USING"关键字连接三个表并使用mysql语法显示