从MySQL中的时间戳排序表中按列选择第一个和最后一个匹配项

从MySQL中的时间戳排序表中按列选择第一个和最后一个匹配项,mysql,geolocation,Mysql,Geolocation,堆栈溢出 我需要你的帮助 假设我在MySQL中有一个如下所示的表: ------------------------------------------------- OWNER_ID | ENTRY_ID | VEHICLE | TIME | LOCATION ------------------------------------------------- 1|1|123456|2016-01-01 00:00:00|A 1|2|123456|2016-01-01 00:01:00|B 1

堆栈溢出

我需要你的帮助

假设我在MySQL中有一个如下所示的表:

-------------------------------------------------
 OWNER_ID | ENTRY_ID | VEHICLE | TIME | LOCATION
-------------------------------------------------
1|1|123456|2016-01-01 00:00:00|A
1|2|123456|2016-01-01 00:01:00|B
1|3|123456|2016-01-01 00:02:00|C
1|4|123456|2016-01-01 00:03:00|C
1|5|123456|2016-01-01 00:04:00|B
1|6|123456|2016-01-01 00:05:00|A
1|7|123456|2016-01-01 00:06:00|A
...
1|999|123456|2016-01-01 09:10:00|A
1|1000|123456|2016-01-01 09:11:00|A
1|1001|123456|2016-01-01 09:12:00|B
1|1002|123456|2016-01-01 09:13:00|C
1|1003|123456|2016-01-01 09:14:00|C
1|1004|123456|2016-01-01 09:15:00|B
...
请注意,表模式只是为了便于我解释而组成的 我想要完成的

假设从条目_ID 6到999,位置列是“A”。我的应用程序基本上只需要第1-6行,然后是第1000行。从第7行到999行的所有内容都是不必要的数据,不需要进一步处理。我正在努力做的是忽略这些行,而不必将数据处理移到我的应用程序中,或者更好的是,删除它们

我对此感到挠头是因为:

1) 我不能按位置排序,然后只取第一个和最后一个条目,因为时间顺序对我的应用程序很重要,这将丢失—例如,如果我以这种方式处理这些数据,我将得到第1行和第1000行,丢失第6行

2) 我不希望将这些数据的处理转移到我的应用程序中,这些数据对于我的需求来说是多余的,如果我可以避免的话,保留这些数据是毫无意义的

鉴于上述示例数据,一旦我有了解决方案,我希望得到的结果是:

-------------------------------------------------
 OWNER_ID | ENTRY_ID | VEHICLE | TIME | LOCATION
-------------------------------------------------
1|1|123456|2016-01-01 00:00:00|A
1|2|123456|2016-01-01 00:01:00|B
1|3|123456|2016-01-01 00:02:00|C
1|4|123456|2016-01-01 00:03:00|C
1|5|123456|2016-01-01 00:04:00|B
1|6|123456|2016-01-01 00:05:00|A
1|1000|123456|2016-01-01 09:11:00|A
1|1001|123456|2016-01-01 09:12:00|B
1|1002|123456|2016-01-01 09:13:00|C
1|1003|123456|2016-01-01 09:14:00|C
1|1004|123456|2016-01-01 09:15:00|B
...
希望我在这里讲得通,没有遗漏一些明显的东西


@Aliester-是否有方法确定行不需要 从该行中包含的数据进行处理

不幸的是没有


@琼斯-听起来你希望确定最早和最新的 表中每个条目ID的不同值的最新时间戳, 然后从与这些行匹配的表中检索详细信息行 时间戳。对吗?您的输入ID值是否唯一?是吗 保证按时间升序?你的问题可以提出 如果这是真的,那就便宜些。如果你有时间,请编辑你的问题 为了澄清这些观点


我试图找到到达某个地点的时间,然后是离开该地点的时间。是的,输入ID是一个唯一的字段,但您不能认为较早的输入ID等于较早的时间戳-传入数据是从车辆上的GPS装置发送的,由于网络限制,不必按照发送顺序进行处理。

这在SQL中是一个棘手的问题,因为SQL是关于数据集的,而不是数据序列。在MySQL中,这是一个特别棘手的问题,因为其他SQL变体都有一个合成的ROWNUM函数,而MySQL到2016年底还没有

这里需要两组数据的并集

  • 位置更改之前的数据库行集
  • 位置更改后的一组行
  • 要实现这一点,您需要从生成所有行的子查询开始,按
    VEHICLE
    排序,然后按
    TIME
    排序,并带有行号。()请注意,Sql FIDLE中的示例数据与您的示例数据不同

           SELECT (@rowa := @rowa + 1) rownum,
                   loc.*
              FROM loc
              JOIN (SELECT @rowa := 0) init
             ORDER BY VEHICLE, TIME
    
    然后,您需要自联接该子查询,使用ON子句排除同一位置的连续行,并在位置更改之前获取这些行。比较连续的行是通过在。。。b、 rownum=a.rownum+1。这就是这个问题。()

    而且,在下一代MySQL中,在MariaDB 10.2的测试版中,这要容易得多。新一代通用表表达式和行编号

     with loc as
         (
                SELECT  ROW_NUMBER() OVER (PARTITION BY VEHICLE ORDER BY time) rownum,
                       loc.*
                  FROM loc
    )
    
    select a.* 
     from loc a
     join loc b ON a.VEHICLE = b.VEHICLE
               AND b.rownum = a.rownum + 1
               AND a.location <> b.location
     union 
    select b.* 
     from loc a
     join loc b ON a.VEHICLE = b.VEHICLE
               AND b.rownum = a.rownum + 1
               AND a.location <> b.location
    order by vehicle, time
    
    带有loc作为
    (
    在(按车辆顺序按时间划分)rownum上选择ROW_NUMBER(),
    loc*
    从loc
    )
    选择一个*
    来自loc a
    连接a车辆上的loc b=b车辆
    和b.rownum=a.rownum+1
    a.地点b.地点
    联合
    选择b.*
    来自loc a
    连接a车辆上的loc b=b车辆
    和b.rownum=a.rownum+1
    a.地点b.地点
    按车辆、时间订购
    
    是否有一种方法可以确定一行不需要根据该行中包含的数据进行处理?听起来您希望为
    条目ID的每个不同值确定表中最早和最新的时间戳,然后从与这些时间戳匹配的表中检索详细信息行。对吗?您的
    条目ID
    值是否唯一?它们是否保证按时间升序排列?如果这是真的,你的查询会更便宜。如果您有时间,请回答您的问题,以澄清这些要点。以便进一步澄清。在您的第一个示例中,是什么使第1行和第6行与要保留的数据集相关,以及是什么使第7行与该数据集无关?@O.Jones,想想火车和铁路时刻表:)我认为是运输。但是,又是什么使得第7行不相关,而第1行和第6行都相关?它们似乎都指向位置
    A
    SELECT a.*
      FROM (
            SELECT (@rowa := @rowa + 1) rownum,
                   loc.*
              FROM loc
              JOIN (SELECT @rowa := 0) init
             ORDER BY VEHICLE, TIME
    ) a 
     JOIN (
             SELECT (@rowb := @rowb + 1) rownum,
                   loc.*
              FROM loc
              JOIN (SELECT @rowb := 0) init
             ORDER BY VEHICLE, TIME
     ) b ON a.VEHICLE = b.VEHICLE AND b.rownum = a.rownum + 1  AND a.location <> b.location
    
     UNION
    
     SELECT d.*
      FROM (
            SELECT (@rowc := @rowc + 1) rownum,
                   loc.*
              FROM loc
              JOIN (SELECT @rowc := 0) init
             ORDER BY VEHICLE, TIME
    ) c 
     JOIN (
             SELECT (@rowd := @rowd + 1) rownum,
                   loc.*
              FROM loc
              JOIN (SELECT @rowd := 0) init
             ORDER BY VEHICLE, TIME
     ) d ON c.VEHICLE = d.VEHICLE AND c.rownum = d.rownum - 1  AND c.location <> d.location
     order by VEHICLE, TIME
    
     with loc as
         (
                SELECT  ROW_NUMBER() OVER (PARTITION BY VEHICLE ORDER BY time) rownum,
                       loc.*
                  FROM loc
    )
    
    select a.* 
     from loc a
     join loc b ON a.VEHICLE = b.VEHICLE
               AND b.rownum = a.rownum + 1
               AND a.location <> b.location
     union 
    select b.* 
     from loc a
     join loc b ON a.VEHICLE = b.VEHICLE
               AND b.rownum = a.rownum + 1
               AND a.location <> b.location
    order by vehicle, time