MySQL计算相邻两行某列差值的方法
简述
博主最近因工作任务缠身,都无暇顾及到我的这片自留地了。前段时间稍有空闲,花了较多的精力学习《啊哈算法》,从中学习到很多之前没有太注重的内容,收益颇丰。但是这些算法题目还没有看完,等后面有时间了,还需重新自我温习一下前面所写的内容,并且继续耕耘后面的算法知识。
今天稍微有点时间,总结一下博主近期工作中所遇到的一些难题,希望借此机遇总结一下类似问题的解决方法,也算是一种积累吧。
背景
我们在司机的手机APP里预置了定时上报GPS数据的功能,功能设置为了APP每15秒收集一次GPS定位地址,然后每收集到10次就上报到服务器端持久化。但因为APP非安卓系统集成,而是由我方自主提供并设计了此功能,那么GPS数据的收集就有可能因司机人为操作或者其他网络等的影响,产生定位偏差或者获取定位失败的情况。现在我们服务端就有这么一个需求,要求分析出安装在司机手机中的APP是否定期收集到了GPS位置。
为了保证GPS定位数据能够较为顺利的上传到服务器端,我们在APP每次请求完服务器端之后,只有当APP接收到来自服务器的正确回应,才能表示这次上传数据是正常且准确的,然后清空掉APP端上一次记录的GPS定位数据;但是如果APP因为各种原因无法将上一次收集的数据上报的服务器端,再尝试一番之后无果,将会在下一次与下一批收集到的数据一同上报,通过此机制来保证数据传递的稳定性。
分析
如果司机手机中的APP是定时15秒就收集到GPS地址的话,那么持久化到数据库中按获取时间顺序排列的前后两条记录的时间差应该就是15秒了,如果大于了15秒,那么就说明定时获取出现了问题。那么现在我们要做的,就是筛选出前后两条记录在获取GPS位置的时间差是否大于15秒,计算时间差的方法在MySQL中已经有了,那就是TimeDiff(对于TimeDiff在Java中使用的小坑我前面的博文有所总结,有兴趣的朋友可以Mark一下,后面抽时间看看。),而对于计算前后两条记录怎么计算差值,这好像确实没有接触过,那么本篇文章就来解决这个问题。
传送门:SQL函数TIMEDIFF在Java程序中使用报错的问题分析
https://www.cnblogs.com/captainad/p/10855608.html
解决
首先博主在服务端有一个表来记录司机上报上来的GPS点位信息,表结构如下:
-- 司机GPS收集表
CREATE TABLE captainad_driver_gps_position (
id BIGINT NOT NULL auto_increment COMMENT '主键',
business_id BIGINT DEFAULT NULL COMMENT '业务ID',
device_mac VARCHAR (64) DEFAULT NULL COMMENT '设备MAC地址',
device_imei VARCHAR (64) DEFAULT NULL COMMENT '设备IMEI',
lat_lng VARCHAR (64) DEFAULT NULL COMMENT '纬经度',
capture_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '捕获时间',
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (id),
KEY `idx_business_id` (`business_id`) USING BTREE
) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT = '司机GPS收集';
表中记录的数据大致如下:

现在就对按获取GPS位置的时间capture_time在按照时间排序之后,进行前后两条记录计算差值。为了计算两者的差值,那么我们肯定是需要获取到一前一后两条记录的,这里我们可以巧用一个变量来记录当前行的行数,然后随着循环查询每次将行数叠加,以达到行记录的目的,这样一来,我们就能知道哪两条记录是一前一后的了。
打印行号的SQL语句:
SELECT
(@rownum := @rownum + 1) AS rownum,
tab.business_id,
tab.device_mac,
tab.capture_time
FROM
captainad_driver_gps_position tab,
(SELECT @rownum := 0) r -- 声明变量
WHERE
1 = 1
AND DATE_FORMAT(
tab.capture_time,
'%Y-%m-%d'
) = '2019-06-28'
ORDER BY
tab.capture_time
基于此,我们将目标SQL给写出来,这里我根据我们的实际业务将语句稍微做了整理,脚本大致如下:
SELECT
t.business_id,
t.device_mac,
t.capture_time,
t.tdiff
FROM
(
SELECT
r1.business_id,
r1.device_mac,
r1.capture_time,
TIMEDIFF(
r2.capture_time,
r1.capture_time
) AS 'tdiff'
FROM
(
SELECT
(@rownum := @rownum + 1) AS rownum,
tab.business_id,
tab.device_mac,
tab.capture_time
FROM
captainad_driver_gps_position tab,
(SELECT @rownum := 0) r
WHERE
1 = 1
AND DATE_FORMAT(
tab.capture_time,
'%Y-%m-%d'
) = '2019-06-28'
ORDER BY
tab.capture_time
) r1
LEFT JOIN (
SELECT
(@INDEX := @INDEX + 1) AS rownum,
tab.business_id,
tab.device_mac,
tab.capture_time
FROM
captainad_driver_gps_position tab,
(SELECT @INDEX := 0) r
WHERE
1 = 1
AND DATE_FORMAT(
tab.capture_time,
'%Y-%m-%d'
) = '2019-06-28'
ORDER BY
tab.capture_time
) r2 ON r1.business_id = r2.business_id
AND r1.device_mac = r2.device_mac
AND r1.rownum = r2.rownum - 1
) t
WHERE
t.tdiff > '00:00:15'
在上面的代码中,我们通过 r1.rownum = r2.rownum - 1来判断两条记录是否是前后行,然后再使用TIMEDIFF函数来计算时间差,到此,我们的目标就实现了。
MySQL计算相邻两行某列差值的方法的更多相关文章
- php 日期 - 计算2个日期的差值
/** * 日期-计算2个日期的差值 * @return int */ public function get_difference($date, $new_date) { $date = strto ...
- C 语言实例 - 计算两个时间段的差值
C 语言实例 - 计算两个时间段的差值 C 语言实例 C 语言实例 计算两个时间段的差值. 实例 #include <stdio.h> struct TIME { int seconds; ...
- oracle计算两个时间的差值(XX天XX时XX分XX秒)
在工作中需要计算两个时间的差值,结束时间 - 开始时间,又不想在js里写function,也不想在java里去计算,干脆就在数据库做了一个函数来计算两个时间的差值.格式为XX天XX时XX分XX秒: 上 ...
- 【HANA系列】SAP HANA SQL计算两个日期的差值
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL计算两个 ...
- javascript 计算两个日期的差值
代码 Typescript版 /** * TimeSpan just like the class TimpSpan in C# ,represent the time difference * @c ...
- MySQL 批量修改某一列的值为另外一个字段的值
mysql> select * from fruit; +----+--------+-------+ | id | name | price | +----+--------+-------+ ...
- 用Scala实现集合中相邻元素间的差值
欢迎转载,转载请注明出处,徽沪一郎. 概要 代码这东西,不写肯定不行,新学Scala不久,将实际遇到的一些问题记录下来,日后也好查找. 今天讲的是如何计算同一集合中元素两两之间的差值,即求开始集合(a ...
- mysql获取插入时自增ID值的方法
1. LAST_INSERT_ID: LAST_INSERT_ID 是与table无关的,如果向表a插入数据后,再向表b插入数据,LAST_INSERT_ID会改变. LAST_INSERT_ID是 ...
- JavaScript获取table中某一列的值的方法
1.实现源码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www. ...
随机推荐
- 关于在php中变量少写了一个$和页面不断转圈的问题排查和vim的自动补全方式
php中的所有变量都是页面级的, 即任何一个页面, 最多 都只能在一个文件 : 当前页面内使用, 不存在跨 文件/ 跨页面的 作用域的变量! 因此, 即使是 $GLOBALS 这个变量, 虽然叫全局 ...
- mysql原生sql处理,按逗号拆分列为多行
举例: id value 1 1,2,3,4 2 2,3,4,5,6 拆分成: id value 1 1 2 2 3 3 4 4 5 5 6 6 ),) ) distinct:去重复操作 a.valu ...
- C++ 已知两个时间(年月日)求日期差
转载:https://blog.csdn.net/flyyufenfei/article/details/79796035 #include<iostream> #include < ...
- Java基础 awt Font 四种字体样式
JDK :OpenJDK-11 OS :CentOS 7.6.1810 IDE :Eclipse 2019‑03 typesetting :Markdown code ...
- (原创)C++ 同步队列
(原创)C++ 同步队列 同步队列作为一个线程安全的数据共享区,经常用于线程之间数据读取,比如半同步半异步线程池的同步队列. 其实做起来比较简单,要用到list.锁和条件变量,条件变量的作用是在队列满 ...
- google cloud storage products
https://cloud.google.com/products/storage/ BigTable Cloud Bigtable 是 Google 面向大数据领域的 NoSQL 数据库服务.它也是 ...
- OpenShift 3.11离线环境的jenkins演示
离线安装完成后,一般情况下只装了个基础环境,catalog镜像没有导入,本文主要侧重在jenkins的一些环境设置和演示. 1.导入镜像 首先follow下面链接下载镜像 https://docs.o ...
- Maya编程——沿Curve绘制圆柱
操作流程: 1. VS运行代码,生成插件 2. 打开Maya绘制曲线,加载插件 3. 选中绘制的曲线,运行插件 Posts1.0 代码: #include <maya/MSimple.h> ...
- 使用 Alibaba 的 Homebrew 镜像源进行加速
使用 Alibaba 的 Homebrew 镜像源进行加速 平时我们执行 brew 命令安装软件的时候,跟以下 3 个仓库地址有关: brew.git homebrew-core.git homebr ...
- 从原生Android 跳转到hbuilder项目
原文地址:https://blog.csdn.net/pentablet/article/details/80277157 前段时间做项目,需要把别人做的hbuilder项目,添加到自己的app中,找 ...