mysql 获取相邻数据项


Posted in MySQL onMay 11, 2022

通过当前排序字段获取相邻数据项

1.业务场景

(1)需要专门以一个弹窗页面展示一项数据的所有字段值.其中一些字段值长度较大。

(2)能够左右切换上一项下一项数据

(3)存在可排序的字段,如以id进行排序

2.思路

2.1 sql

1>查询前一项,查询小于当前id的项逆序取第一个

2>查询后一项,查询大于当前id的项正序取第一个

3>连接两项结果

2.2 页面逻辑

(1)在展示当前项时获取好两相邻的数据,在做切换时直接填充数据

(2)切换数据展示时同样再次获取当前项两相邻数据

以此(1)(2)往复

3.sql

例:查询id为40两相邻的数据

( SELECT * FROM [表名] WHERE id < 40 ORDER BY id DESC LIMIT 1 ) UNION
(
    SELECT
        * 
    FROM
        [表名]
    WHERE
        id > 40 
    ORDER BY
        id 
    LIMIT 1
)

同表相邻数据查询或计算

用户下相邻订单的时间差举例

这里主要介绍一下,在一张数据表下对相邻的数据进行一个相关查询和计算;

拿一个在电商中最常见的情况,计算一下用户首单和第二单的时间间隔这样的数据来举例,如下:

id customer_id created_at
1 1 2017-07-21 09:43:02
2 12 2017-07-25 11:37:48
3 10 2017-07-25 11:43:41
4 1 2017-07-27 01:27:22
5 10 2017-07-27 07:46:45
6 1 2017-07-27 10:21:37
7 12 2017-07-27 13:26:19

查询用户首单和第二单的时间间隔:

SELECT
	m.customer_id,
	sfo.created_at as '首单时间',
	m.created_at as '第二单时间',
	(unix_timestamp(m.created_at) - unix_timestamp(sfo.created_at))/86400 as '两单相差天数'
	
FROM
	sales_flat_order m 
LEFT JOIN 
	sales_flat_order sfo on m.customer_id = sfo.customer_id and sfo.created_at < m.created_at
WHERE
	(
		SELECT
			count(*)
		FROM
			sales_flat_order n
		WHERE
			m.customer_id = n.customer_id
			AND m.created_at > n.created_at
	) = 1
GROUP BY m.customer_id

查询结果是:

customer_id 首单时间 第二单时间 两单时间差
1 2017-07-21 09:43:02 2017-07-27 01:27:22 5.6558
12 2017-07-25 11:37:48 2017-07-27 13:26:19 2.0754
10 2017-07-25 11:43:41 2017-07-27 07:46:45 1.8355

整个原理如下:

  • 将一张表查询两次得到两组数据,分别为别名m和别名n的两组数据;
  • 以m为主,用n的数据和m的数据作对比,通过created_at的判断过滤掉一些无用数据;
  • 使用count()函数统计满足条件的数据个数;
  • 统计数为1时说明n表中比m表中时间小的只有1条,m中的该条数据也就是该用户下的第二笔订单;
  • 通过LEFT JOIN联表,通过created_at找到比第二单更早的一单也就是用户的首单;
  • 利用unix_timestamp把得到的两条数据的created_at做差,得到了两笔订单的时间间隔;

下面做了一下拓展,可以查询任意相连的两笔订单的时间间隔:

SELECT
	m.customer_id,
	m.created_at as '后一单时间',
	SUBSTRING_INDEX(
		GROUP_CONCAT(sfo.created_at ORDER BY sfo.created_at DESC),
		',',
		1
	) as '前一单时间',
	(unix_timestamp(m.created_at) - unix_timestamp(
		SUBSTRING_INDEX(
			GROUP_CONCAT(sfo.created_at ORDER BY sfo.created_at DESC),
			',',
			1
		)
	))/86400 as '两单相差天数'
FROM
	sales_flat_order m 
LEFT JOIN 
	sales_flat_order sfo on m.customer_id = sfo.customer_id and sfo.created_at < m.created_at
WHERE
	(
		SELECT
			count(*)
		FROM
			sales_flat_order n
		WHERE
			m.customer_id = n.customer_id
			AND m.created_at > n.created_at
	) = 2
GROUP BY m.customer_id;

得到数据如下:

customer_id 后一单时间 前一单时间 两单时间差
1 2017-07-27 10:21:37 2017-07-27 01:27:22 0.3710

这里判断的是统计数为2的,也就是用户的第二单和第三单的时间间隔计算,因为用户10和12只有两单所以结果中无这两个用户;

整个原理如下:

  • 将一张表查询两次得到两组数据,分别为别名m和别名n的两组数据;
  • 以m为主,用n的数据和m的数据作对比,通过created_at的判断过滤掉一些无用数据;
  • 使用count()函数统计满足条件的数据个数;
  • 筛选之后m中得到的是第三笔订单;
  • 通过LEFT JOIN联表,通过created_at找到比第三笔订单时间早的订单,这里会从sfo中得到两笔订单;
  • 利用GROUP_CONCAT函数每组订单中各得到的两笔订单利用created_at进行降序排序,然后得到通过‘,’连接的两条数据的时间,如下:2017-07-27 01:27:22,2017-07-21 09:43:02
  • 使用SUBSTRING_INDEX函数通过’,'将数据拆分再拿到第一条数据,也就是第二笔订单的时间了;
  • 利用unix_timestamp对created_at作差,得到两笔订单的时间间隔;

这只是我想到的应对这种场景通过SQL语句进行查询的方法。 

MySQL 相关文章推荐
详解MySQL 联合查询优化机制
May 10 MySQL
MySQL 可扩展设计的基本原则
May 14 MySQL
mysql 如何获取两个集合的交集/差集/并集
Jun 08 MySQL
MySQL 使用索引扫描进行排序
Jun 20 MySQL
MySQL分库分表详情
Sep 25 MySQL
SQL实战演练之网上商城数据库商品类别数据操作
Oct 24 MySQL
MySQL为数据表建立索引的原则详解
Mar 03 MySQL
MySQL实战记录之如何快速定位慢SQL
Mar 23 MySQL
mysql数据插入覆盖和时间戳的问题及解决
Mar 25 MySQL
MySQL事务操作的四大特性以及并发事务问题
Apr 12 MySQL
MySQL批量更新不同表中的数据
May 11 MySQL
详解Mysql数据库平滑扩容解决高并发和大数据量问题
May 25 MySQL
MySQL脏读,幻读和不可重复读
May 11 #MySQL
MySql数据库 查询时间序列间隔
May 11 #MySQL
Mysql中常用的join连接方式
May 11 #MySQL
MySQL的prepare使用以及遇到的bug
May 11 #MySQL
MySQL批量更新不同表中的数据
May 11 #MySQL
mysql查找连续出现n次以上的数字
May 11 #MySQL
mysql如何查询连续记录
May 11 #MySQL
You might like
php 删除cookie和浏览器重定向
2009/03/16 PHP
详解thinkphp5+swoole实现异步邮件群发(SMTP方式)
2017/10/13 PHP
论坛特效代码收集(落伍转发-不错)
2006/12/02 Javascript
JavaScript 事件记录使用说明
2009/10/20 Javascript
在父页面调用子页面的JS方法
2013/09/29 Javascript
jQuery简单图表peity.js使用示例
2014/05/02 Javascript
浅谈javascript中for in 和 for each in的区别
2015/04/23 Javascript
深入剖析JavaScript面向对象编程
2016/07/12 Javascript
详解EasyUi控件中的Datagrid
2017/08/23 Javascript
vue复合组件实现注册表单功能
2017/11/06 Javascript
解决在Bootstrap模糊框中使用WebUploader的问题
2018/03/22 Javascript
浅谈使用mpvue开发小程序需要注意和了解的知识点
2018/05/23 Javascript
React router动态加载组件之适配器模式的应用详解
2018/09/12 Javascript
微信小程序动态显示项目倒计时
2019/06/20 Javascript
小程序表单认证布局及验证详解
2020/06/19 Javascript
viewer.js实现图片预览功能
2020/06/24 Javascript
在vue中使用echarts(折线图的demo,markline用法)
2020/07/20 Javascript
解决vue 给window添加和移除resize事件遇到的坑
2020/07/21 Javascript
Vue 使用typescript如何优雅的调用swagger API
2020/09/01 Javascript
Python正则表达式分组概念与用法详解
2017/06/24 Python
Python浅复制中对象生存周期实例分析
2018/04/02 Python
Django 实现购物车功能的示例代码
2018/10/08 Python
python使用magic模块进行文件类型识别方法
2018/12/08 Python
python文件选择对话框的操作方法
2019/06/27 Python
Python3如何在服务器打印资产信息
2020/08/27 Python
python re模块常见用法例举
2021/03/01 Python
使用jquery实现HTML5响应式导航菜单教程
2014/04/02 HTML / CSS
世界上最全面的汽车零部件和配件集合:JC Whitney
2016/09/04 全球购物
马来西亚领先的在线礼品店:Giftr
2018/08/23 全球购物
技校教师求职简历的自我评价
2013/10/20 职场文书
白酒营销策划方案
2014/08/17 职场文书
2015年小学美术工作总结
2015/05/25 职场文书
入党团支部推荐意见
2015/06/02 职场文书
蓝天保卫战收官在即 :15行业将开展环保分级评价
2019/07/19 职场文书
一文搞懂php的垃圾回收机制
2021/06/18 PHP
15个值得收藏的JavaScript函数
2021/09/15 Javascript