如何选择min和;子集组的最大值

时间:2014-07-11 13:47:09

标签: mysql

我试图解决以下问题,我有一个跟踪设备,每分钟都会更新其位置和在线状态。我试图通过将在线状态分组为select语句的几个小子集来将这些数据拆分为单独的旅程。

我知道我可以选择min&最大限度地将这些用于整个表格,但我不确定如何为其在线状态为真的每个组执行此操作。

虽然我可以在代码中实现所需的结果,但我需要将此操作移到服务器上,以满足电线性能的原因。

任何人都可以帮我指出正确的方向将其分解为sql语句吗?

[positions]
+-------------------+-----------------------+------+-----+---------+----------------+
| Field             | Type                  | Null | Key | Default | Extra          |
+-------------------+-----------------------+------+-----+---------+----------------+
| id                | int          unsigned | NO   | PRI | NULL    | auto_increment |
| device_id         | int          unsigned | NO   |     | NULL    |                |
| lat               | double                | NO   |     | 0       |                |
| lng               | double                | NO   |     | 0       |                |
| date_time         | datetime              | NO   |     | NULL    |                |
| online            | bit                   | NO   |     | 0       |                |
+-------------------+-----------------------+------+-----+---------+----------------+

示例数据

id  device_id   lat     lng     date_time             online
14  1           0.1     0.1     2014-07-11 05:21:37   0
17  1           0.11    0.11    2014-07-11 05:22:37   1 
18  1           0.12    0.12    2014-07-11 05:23:37   1
24  1           0.13    0.13    2014-07-11 05:24:37   1
25  1           0.14    0.14    2014-07-11 05:25:37   1
26  1           0.14    0.14    2014-07-11 05:26:37   0
45  1           0.14    0.14    2014-07-11 05:27:37   0
47  1           0.14    0.14    2014-07-11 05:28:37   1
56  1           0.13    0.13    2014-07-11 05:29:37   1
67  1           0.12    0.12    2014-07-11 05:30:37   1
68  1           0.11    0.11    2014-07-11 05:31:37   1
78  1           0.11    0.11    2014-07-11 05:32:37   0

期望的结果

StartDateTime        StartLat StartLng  FinishDateTime       FinishLat FinishLng
2014-07-11 05:22:37  0.11     0.11      2014-07-11 05:25:37  0.14      0.14
2014-07-11 05:28:37  0.14     0.14      2014-07-11 05:31:37  0.11      0.11

提前致谢, 史蒂夫

1 个答案:

答案 0 :(得分:1)

您需要描述每个组的特征。最简单的方法是计算每行前online = 0的数量:

select device_id, min(date_time) as StartDateTime, max(date_time) as FinishDateTime,
       substring_index(group_concat(lat order by datetime asc), ',', 1) as StartLat,
       substring_index(group_concat(long order by datetime asc), ',', 1) as StartLong,
       substring_index(group_concat(lat order by datetime desc), ',', 1) as EndLat,
       substring_index(group_concat(long order by datetime desc), ',', 1) as EndLong
from (select e.*,
             (select count(*)
              from example e2
              where e2.device_id = e.device_id and
                    e2.date_time <= e.date_time and
                    e2.online = 0
             ) as grp
      from example e
      where e.online = 1
     ) e
group by device_id, grp;

这会使用substring_index() / group_concat()技巧获取第一个和最后一个值。

select t.*,
       efirst.lat as firstLat, efirst.long as firstLong,
       ellast.lat as lastLat, elast.long as lastLong
from (select device_id, min(date_time) as StartDateTime, max(date_time) as FinishDateTime
      from (select e.*,
                   (select count(*)
                    from example e2
                    where e2.device_id = e.device_id and
                          e2.date_time <= e.date_time and
                          e2.online = 0
                   ) as grp
            from example e
            where e.online = 1
           ) e
      group by device_id, grp
     ) t join
     example efirst
     on efirst.device_id = t.device_id and efirst.date_time = FirstDateTime join
     example elast
     on elast.device_id = t.device_id and elast.date_time = FinishDateTime;