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 相关文章推荐
详解GaussDB for MySQL性能优化
May 18 MySQL
.Net Core导入千万级数据至Mysql的步骤
May 24 MySQL
MySQL高速缓存启动方法及参数详解(query_cache_size)
Jul 01 MySQL
记一次Mysql不走日期字段索引的原因小结
Oct 24 MySQL
如何创建一个创建MySQL数据库中的datetime类型
Mar 21 MySQL
mysql中DCL常用的用户和权限控制
Mar 31 MySQL
pt-archiver 主键自增
Apr 26 MySQL
MySQL 字符集 character
May 04 MySQL
MySQL8.0 Undo Tablespace管理详解
Jun 16 MySQL
MySQL主从切换的超详细步骤
Jun 28 MySQL
关于MySQL中explain工具的使用
May 08 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-redis中文文档介绍
2013/02/07 PHP
php之XML转数组函数的详解
2013/06/07 PHP
PHP对称加密算法(DES/AES)类的实现代码
2017/11/14 PHP
用js实现计算代码行数的简单方法附代码
2007/08/13 Javascript
json 定义
2008/06/10 Javascript
基于jQuery的的一个隔行变色,鼠标移动变色的小插件
2010/07/06 Javascript
模仿百度三维地图的js数据分享
2011/05/12 Javascript
非常好用的JsonToString 方法 简单实例
2013/07/18 Javascript
JSONP获取Twitter和Facebook文章数的具体步骤
2014/02/24 Javascript
jQuery实现的向下图文信息滚动效果
2015/05/03 Javascript
jQuery动态效果显示人物结构关系图的方法
2015/05/07 Javascript
全面解析Bootstrap表单使用方法(表单按钮)
2015/11/24 Javascript
简单介绍JavaScript数据类型之隐式类型转换
2015/12/28 Javascript
javascript中对Date类型的常用操作小结
2016/05/19 Javascript
JavaScript编写的网页小游戏,很给力
2017/08/18 Javascript
vue引入ueditor及node后台配置详解
2018/01/03 Javascript
使用iView Upload 组件实现手动上传图片的示例代码
2018/10/01 Javascript
通过JS运行机制的角度说说作用域
2019/03/12 Javascript
vue实现todolist基本功能以及数据存储功能实例详解
2019/04/11 Javascript
angular6开发steps步骤条组件
2019/07/04 Javascript
Vue项目中如何使用Axios封装http请求详解
2019/10/23 Javascript
Openlayers绘制聚合标注
2020/09/28 Javascript
[01:12]DOTA2次级职业联赛 - Newbee.Y 战队宣传片
2014/12/01 DOTA
Python数据分析之如何利用pandas查询数据示例代码
2017/09/01 Python
Python_LDA实现方法详解
2017/10/25 Python
Python实现全排列的打印
2018/08/18 Python
Python基础之循环语句用法示例【for、while循环】
2019/03/23 Python
python3.8 微信发送服务器监控报警消息代码实现
2019/11/05 Python
Sofft鞋官网:世界知名鞋类品牌
2017/03/28 全球购物
美国迪克体育用品商店:DICK’S Sporting Goods
2018/07/24 全球购物
Spongelle官网:美国的创意护肤洗护品牌
2019/05/15 全球购物
提高EJB性能都有哪些技巧
2012/03/25 面试题
党员个人整改措施
2014/10/24 职场文书
100句拼搏进取的名言警句,值得一读!
2019/10/07 职场文书
基于MySql验证的vsftpd虚拟用户
2021/11/07 MySQL
画错魏国疆域啦!《派对咖孔明》动画因作画失误于官网致歉
2022/04/07 日漫