将多行的日期汇总为一个

时间:2013-11-27 18:44:12

标签: 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 :)。

1 个答案:

答案 0 :(得分:1)

试试这个

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