今天突然想到了一个需求,即在一张带有id和time字段的表中,查询相邻时间的时间差。

  • 表的记录如下:

表名为wangxin

id是一个不重复的字符串,time是一个时间戳。

  • 现在的需求如下:

比如id分别有wangxin1到wangxin4的几个椅子,小王同学,先坐上wangxin1的椅子,然后坐了几秒后,又坐到了编号为wangxin2的椅子上,然后一会儿又换到了wangxin3的椅子上,最后坐到wangxin4的椅子上,问,分别在每一个椅子上坐的时间。最后一个默认为0.

  • 需求解决思路

想要知道差值,那就意味着必须把时间都比一下,可是只有一张表怎么办,就只能使用子查询的方式,利用内连接,获取到笛卡尔积,即一个时间点对应四个时间点,这样一来,就方便对其进行一个运算了。

-- 第一步,创建笛卡尔积
SELECT
w1.*, w2.*
FROM
wangxin w1
INNER JOIN (SELECT w3.time FROM wangxin w3) w2 ;

使用内连接的方式创建笛卡尔积,如下所示,这是用来方便计算两个时间点的差值的:

-- 第二步,进行运算
SELECT
w1.id, w1.time,w2.time-w1.time as time_diff
FROM
wangxin w1
INNER JOIN (SELECT w3.time FROM wangxin w3) w2 ;

这一步运算就是为了计算出两次的时间差,可见,我们需要的是相近时间点的差值,并且因为是差值,所以只能大于0,故我们第三步整理中,以上一步的结果作为一个新的表,再进行一次select操作,同时我们以time字段分组,并且取time_diff字段非0以外的最小值。

-- 第三步,整理
SELECT
t1.id,
t1.time,
MIN(t1.time_diff) AS time_diff
FROM
(
SELECT
w1.id,
w1.time,
w2.time - w1.time AS time_diff
FROM
wangxin w1
INNER JOIN (SELECT w3.time FROM wangxin w3) w2
) t1
WHERE
t1.time_diff > 0
GROUP BY
t1.time

这时候,我们发现了咦,为什么wangxin4这个记录没有了,原来是因为我们上面采用的是时间差大于0的情况,由于wangxin4后面就没有新的时间戳了,所以无法计算时间差,故其时间差为0,在上一步的where语句中被略去。

最后我们再加上一不外链接

-- 加回原来的表中
SELECT
t.*, IFNULL(t2.time_diff, 0) as '时间差'
FROM
wangxin t
LEFT JOIN (
SELECT
t1.id,
t1.time,
MIN(t1.time_diff) AS time_diff
FROM
(
SELECT
w1.id,
w1.time,
w2.time - w1.time AS time_diff
FROM
wangxin w1
INNER JOIN (SELECT w3.time FROM wangxin w3) w2
) t1
WHERE
t1.time_diff > 0
GROUP BY
t1.time
) t2 ON t.id = t2.id

这一步外链接里面需要注意的是,因为上一次的表中没有id为wangxin4这个记录,所以在左外链接的情况下,就会变成null,因此我们在select语句中,需要对这种情况做一个判断,判断是否为null,如果是null的话,就让这个单元格设置为0

最终结果为:

结果和想象中的一样。

总结:

之前一直觉得sql很简单,随便写写就行了,但是今天接触了一个非常复杂的sql,顿时觉得自己先前真的太幼稚了,sql相对于java更贴近算法,从书写到优化,发现sql是一门非常厉害的技术,自愧不如、自愧不如哇!

需要学习的东西还很多,与君共勉!

sql查询两条记录的时间差的更多相关文章

  1. SQLServer 分组查询相邻两条记录的时间差

    原文:SQLServer 分组查询相邻两条记录的时间差 首先,我们通过数据库中表的两条记录来引出问题,如下图 以上为一个记录操作记录的表数据.OrderID为自增长列,后面依次为操作类型,操作时间,操 ...

  2. hive实现根据用户分组,按用户记录求上下两条记录的时间差

    在mysql,数据如下:#查询某一用户该日抽奖时间 select draw_time from user_draw_log where user_id = 1 and draw_date='2016- ...

  3. sql查询某条记录

    select * from (SELECT t.*,ROWNUM AS RN FROM AWARDISSUE_FOOTBALL t ORDER BY ID DESC) WHERE RN=2

  4. SQL查找TCar表中同一辆车前后两条记录的CarId,两条记录中有多个字段值一样

    查询同一个表中某一字段值相同的记录 select * from 表名 where 字段 in(select 字段 from 表名 group by 字段 having count(1)>1) s ...

  5. SQL查询多条不重复记录值简要解析【转载】

    转载http://hi.baidu.com/my_favourate/item/3716b0cbe125f312505058eb SQL查询多条不重复记录值简要解析2008-02-28 11:36 以 ...

  6. 【面经】面试官:如何以最高的效率从MySQL中随机查询一条记录?

    写在前面 MySQL数据库在互联网行业使用的比较多,有些小伙伴可能会认为MySQL数据库比较小,存储不了很多的数据.其实,这些小伙伴是真的不了解MySQL.MySQL的小不是说使用MySQL存储的数据 ...

  7. sqlserver -- 学习笔记(七)获取同组数据的前两条记录

    不啰嗦,直接上图,大概实现效果如下: 有上面这样一份数据,将他们按照userAccount和submitTime进行分组,然后提前每组数据的前两条记录 提取后数据如下: 实现的SQL如下: selec ...

  8. mysql 查询一条记录的下一条和上一条记录

    如果ID是主键或者有索引,可以直接查找: 方法一: 查询上一条记录的SQL语句(如果有其他的查询条件记得加上other_conditions以免出现不必要的错误): select * from tab ...

  9. mysql结构相同的三张表查询一条记录\将一张表中的数据插入另外一张表

    将一张表中的数据插入另外一张表 1.两张表结构相同 insert into 表1名称 select * from 表2名称 2.两张结构不相同的表 insert into 表1名称(列名1,列名2,列 ...

随机推荐

  1. 使用 redis “捕捉” “用户登录过期” 事件

    实现原理及步骤: 1)登录时,计算登录过期时间,以分钟为单位作key(例如:sign_timeout_201705212233),value方面自己发挥,需要什么数据就拼什么数据进去,只是要注意,一定 ...

  2. Linux 查看目录大小及文件数量命令

    查看当前目录大小: [root@21andy.com]# du -sh 查看指定目录大小: [root@21andy.com]# du -sh /www/21andy.com 查看当前目录文件总数: ...

  3. NFS exportfs 命令

    exportfs 是在服务端上使用的命令,主要用来操作挂载的目录,比如我们修改了NFS配置文件,需要重启NFS服务,如果客户端正在读写,那么重启NFS服务对客户端是有影响的,因此 exportfs 命 ...

  4. /etc/issue

    /etc/issue 与 /etc/motd 作用一致,都是用于显示欢迎信息,区别在于 /etc/issue 是在 login 提示符之前显示,而 /etc/motd 则在在用户成功登录系统之后显示 ...

  5. 你必须知道的10个提高Canvas性能技巧

    你还在抱怨自己写的canvas demo徘徊在10帧以下吗?你还在烦恼打开自己写的应用就听见CUP风扇转吗?你正在写一个javascript Canvas库吗?那么下面九点就是你必须知道的! 一.预渲 ...

  6. CoreData 数据库更新,数据迁移

    本文转载至 http://blog.163.com/djx421@126/blog/static/48855136201411381212985/   一般程序app升级时,数据库有可能发生改变,如增 ...

  7. 【cs229-Lecture3】Logistic回归

    参考: http://www.itongji.cn/article/12112cH013.html http://blog.csdn.net/zouxy09/article/details/20319 ...

  8. 【大数据系列】hadoop命令指导官方文档翻译

    Hadoop Commands Guide Overview Shell Options Generic Options User Commands archive checknative class ...

  9. [Error: Failed to find 'ANDROID_HOME' environment variable. Try setting setting it manually

    7down voteaccepted I don't think its necessary to add everything into path.Just add the JAVA_HOME , ...

  10. linux下的一些操作命令

    1.切换到root账号下: su root    输入密码: 2.修改root账号密码: sudo passwd root   输入密码: 3.cat用法: 查看文件内容   cat 文件名 创建文件 ...