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优化
Apr 06 MySQL
mysql查询的控制语句图文详解
Apr 11 MySQL
MySQL数据迁移相关总结
Apr 29 MySQL
MySQL 使用事件(Events)完成计划任务
May 24 MySQL
MySQL不使用order by实现排名的三种思路总结
Jun 02 MySQL
新手入门Mysql--sql执行过程
Jun 20 MySQL
MySQL 聚合函数排序
Jul 16 MySQL
实战 快速定位MySQL的慢SQL
Mar 22 MySQL
MySQL数据库Innodb 引擎实现mvcc锁
May 06 MySQL
mysql幻读详解实例以及解决办法
Jun 16 MySQL
MySQL外键约束(Foreign Key)案例详解
Jun 28 MySQL
MySQL新手入门进阶语句汇总
Sep 23 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 数组排序方法总结 推荐收藏
2010/06/30 PHP
PHP进阶学习之依赖注入与Ioc容器详解
2019/06/19 PHP
Laravel5.1 框架路由基础详解
2020/01/04 PHP
PHP字符串和十六进制如何实现互相转换
2020/07/16 PHP
VSCode+PHPstudy配置PHP开发环境的步骤详解
2020/08/20 PHP
用js实现随机返回数组的一个元素
2007/08/13 Javascript
caller和callee的区别介绍及演示结果
2013/03/10 Javascript
JS匀速运动演示示例代码
2013/11/26 Javascript
JS动态调用方法名示例介绍
2013/12/18 Javascript
js和jquery如何获取图片真实的宽度和高度
2014/09/28 Javascript
提交按钮的name='submit'引起的js失效问题及原因
2015/02/25 Javascript
javascript实现简单的html5视频播放器
2015/05/06 Javascript
JS未跨域操作iframe里的DOM
2016/06/01 Javascript
JS简单去除数组中重复项的方法
2016/09/13 Javascript
微信小程序之发送短信倒计时功能
2017/08/30 Javascript
angular json对象push到数组中的方法
2018/02/27 Javascript
详解如何使用React Hooks请求数据并渲染
2020/10/18 Javascript
vuex中遇到的坑,vuex数据改变,组件中页面不渲染操作
2020/11/16 Javascript
动态实现element ui的el-table某列数据不同样式的示例
2021/01/22 Javascript
Python生成pdf文件的方法
2014/08/04 Python
简介Python的collections模块中defaultdict类型的用法
2016/07/07 Python
Python面向对象编程基础解析(二)
2017/10/26 Python
python2.7 安装pip的方法步骤(管用)
2019/05/05 Python
tensorflow 实现从checkpoint中获取graph信息
2020/02/10 Python
Django models文件模型变更错误解决
2020/05/11 Python
Python dict的常用方法示例代码
2020/06/23 Python
利用CSS3实现平移动画效果示例代码
2016/10/12 HTML / CSS
HTML5本地存储和本地数据库实例详解
2017/09/05 HTML / CSS
皮姆斯勒语言学习:Pimsleur Language Programs
2018/06/30 全球购物
美国领先的家庭健康检测试剂盒提供商:LetsGetChecked
2019/03/18 全球购物
中国梦演讲稿3分钟
2014/08/19 职场文书
开展党的群众路线教育实践活动个人对照检查材料
2014/11/05 职场文书
结婚保证书(三从四德)
2015/02/26 职场文书
网吧温馨提示
2015/07/17 职场文书
运动会广播稿200字
2015/08/19 职场文书
Vue Element plus使用方法梳理
2022/12/24 Vue.js