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 Show Profile
Apr 05 MySQL
详解MySQL主从复制及读写分离
May 07 MySQL
详解MySQL数据库千万级数据查询和存储
May 18 MySQL
解决Mysql的left join无效及使用的注意事项说明
Jul 01 MySQL
Mysql8.0递归查询的简单用法示例
Aug 04 MySQL
SQL实现LeetCode(197.上升温度)
Aug 07 MySQL
解析MySQL索引的作用
Mar 03 MySQL
MySQL Server层四个日志的实现
Mar 31 MySQL
Mysql InnoDB 的内存逻辑架构
May 06 MySQL
MySQL数据库实验之 触发器和存储过程
Jun 21 MySQL
SQL语句中EXISTS的详细用法大全
Jun 25 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
《五等分的花嫁》漫画完结!2020年10月第2期TV动画制作组换血!
2020/03/06 日漫
2019年漫画销量排行榜:鬼灭登顶 海贼单卷制霸 尾田盛赞鬼灭
2020/03/08 日漫
探讨:如何通过stats命令分析Memcached的内部状态
2013/06/14 PHP
php递归遍历删除文件的方法
2015/04/17 PHP
PHP+Ajax实现的博客文章添加类别功能示例
2018/03/29 PHP
BOM与DOM的区别分析
2010/10/26 Javascript
JS 自定义带默认值的函数
2011/07/21 Javascript
jQuery防止click双击多次提交及传递动态函数或多参数
2014/04/02 Javascript
JavaScript 作用域链解析
2014/11/13 Javascript
js操作css属性实现div层展开关闭效果的方法
2015/05/11 Javascript
JavaScript中的Math.LN2属性用法详解
2015/06/12 Javascript
JavaScript的==运算详解
2016/07/20 Javascript
AngularJS入门教程之链接与图片模板详解
2016/08/19 Javascript
JavaScript之iterable_动力节点Java学院整理
2017/06/29 Javascript
Bootstrap modal只加载一次数据的解决办法(推荐)
2017/11/24 Javascript
微信小程序tabBar模板用法实例分析【附demo源码下载】
2017/11/28 Javascript
node.js博客项目开发手记
2018/03/16 Javascript
Vue.js的动态组件模板的实现
2018/11/26 Javascript
vscode vue 文件模板的配置方法
2019/07/23 Javascript
vue+element搭建后台小总结 el-dropdown下拉功能
2020/04/10 Javascript
jquery添加div实现消息聊天框
2020/02/08 jQuery
微信小程序12行js代码自己写个滑块功能(推荐)
2020/07/15 Javascript
jQuery实现可以计算进制转换的计算器
2020/10/19 jQuery
[01:02:06]LGD vs Mineski Supermajor 胜者组 BO3 第二场 6.5
2018/06/06 DOTA
Python 自动补全(vim)
2014/11/30 Python
Python在信息学竞赛中的运用及Python的基本用法(详解)
2017/08/15 Python
python复制文件到指定目录的实例
2018/04/27 Python
python opencv将图片转为灰度图的方法示例
2019/07/31 Python
linux环境下安装python虚拟环境及注意事项
2020/01/07 Python
jupyter notebook的安装与使用详解
2020/05/18 Python
css3高级选择器使用方法
2013/12/02 HTML / CSS
教育科学研究生自荐信
2013/10/09 职场文书
大学生职业规划论文
2014/01/11 职场文书
2014年廉洁自律承诺书
2014/05/26 职场文书
夫妻忠诚协议范文
2014/11/16 职场文书
捐款感谢信
2015/01/20 职场文书