仅用一句SQL更新整张表的涨跌幅、涨跌率的解决方案


Posted in MySQL onMay 06, 2021

问题场景

各大平台店铺的三项评分(物流、服务、商品)变化情况;
商品每日价格的变化记录;
股票的实时涨跌浮;

复现场景

表:主键ID,商品编号,记录时的时间,记录时的价格,创建时间。
问题:获取每个商品每次的变化情况(涨跌幅、涨跌率)。

解决思路

1、要想高效率的更新涨跌,就肯定不能是逐条数据更新,要通过自连表建立起对应关系,将每一条数据关联到上一次的价格数据。

2、由于数据库非常庞大,所以可能存在很多垃圾数据,就比如说相关的字段值为NULL或者非有效值的,这些数据要先排除掉。

SELECT id,goods_code,goods_date,goods_price FROM test_goods_price_change WHERE goods_price IS NOT NULL AND goods_date IS NOT NULL;

3、然后在获取每条数据的上一条数据,同样也要先排除掉垃圾数据。

SELECT tmp_a.*, MAX(tmp_b.goods_date) AS last_date FROM 
( SELECT id,goods_code,goods_date,goods_price FROM test_goods_price_change WHERE goods_price IS NOT NULL AND goods_date IS NOT NULL ) AS tmp_a
LEFT JOIN
( SELECT id,goods_code,goods_date,goods_price FROM test_goods_price_change WHERE goods_price IS NOT NULL AND goods_date IS NOT NULL ) AS tmp_b
ON tmp_a.goods_code = tmp_b.goods_code AND tmp_a.goods_date > tmp_b.goods_date GROUP BY tmp_a.id;

4、获取到上一条数据后,获取上条数据对应的商品价格。

SELECT tmp_ab.*,tmp_c.goods_price AS last_price FROM 
(
	SELECT tmp_a.*, MAX(tmp_b.goods_date) AS last_date FROM 
	( SELECT id,goods_code,goods_date,goods_price FROM test_goods_price_change WHERE goods_price IS NOT NULL AND goods_date IS NOT NULL ) AS tmp_a
	LEFT JOIN
	( SELECT id,goods_code,goods_date,goods_price FROM test_goods_price_change WHERE goods_price IS NOT NULL AND goods_date IS NOT NULL ) AS tmp_b
	ON tmp_a.goods_code = tmp_b.goods_code AND tmp_a.goods_date > tmp_b.goods_date GROUP BY tmp_a.id
) AS tmp_ab 
LEFT JOIN (SELECT id,goods_code,goods_date,goods_price FROM test_goods_price_change WHERE goods_price IS NOT NULL AND goods_date IS NOT NULL ) AS tmp_c
ON tmp_ab.goods_code = tmp_c.goods_code AND tmp_c.goods_date = tmp_ab.last_date ORDER BY tmp_ab.id;

5、获取到上条数据以及对应的价格后,开始进行计算,获取到最终的结果。

SELECT 
	*, 
	(CONVERT(goods_price, DECIMAL(10,2)) - CONVERT(last_price, DECIMAL(10,2))) AS '涨跌幅',
	ROUND((CONVERT(goods_price, DECIMAL(10,2)) - CONVERT(last_price, DECIMAL(10,2)))/CONVERT(last_price, DECIMAL(10,2)), 2) AS '涨跌率' 
FROM (
	SELECT tmp_ab.*,tmp_c.goods_price AS last_price FROM 
	(
		SELECT tmp_a.*, MAX(tmp_b.goods_date) AS last_date FROM 
		( SELECT id,goods_code,goods_date,goods_price FROM test_goods_price_change WHERE goods_price IS NOT NULL AND goods_date IS NOT NULL ) AS tmp_a
		LEFT JOIN
		( SELECT id,goods_code,goods_date,goods_price FROM test_goods_price_change WHERE goods_price IS NOT NULL AND goods_date IS NOT NULL ) AS tmp_b
		ON tmp_a.goods_code = tmp_b.goods_code AND tmp_a.goods_date > tmp_b.goods_date GROUP BY tmp_a.id
	) AS tmp_ab 
	LEFT JOIN (SELECT id,goods_code,goods_date,goods_price FROM test_goods_price_change WHERE goods_price IS NOT NULL AND goods_date IS NOT NULL ) AS tmp_c
	ON tmp_ab.goods_code = tmp_c.goods_code AND tmp_c.goods_date = tmp_ab.last_date ORDER BY tmp_ab.id
) AS tmp

解决方案

-- 创建表SQL
CREATE TABLE `test_goods_price_change` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `goods_code` varchar(50) NOT NULL COMMENT '商品编码',
  `goods_date` int(11) NOT NULL COMMENT '记录时的时间',
  `goods_price` decimal(10,2) NOT NULL COMMENT '记录时的价格',
  `created_at` int(11) NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB CHARSET=utf8mb4;

-- 获取涨跌浮SQL
SELECT 
	*, 
	(CONVERT(goods_price, DECIMAL(10,2)) - CONVERT(last_price, DECIMAL(10,2))) AS '涨跌幅',
	ROUND((CONVERT(goods_price, DECIMAL(10,2)) - CONVERT(last_price, DECIMAL(10,2)))/CONVERT(last_price, DECIMAL(10,2)), 2) AS '涨跌率' 
FROM (
	SELECT tmp_ab.*,tmp_c.goods_price AS last_price FROM 
	(
		SELECT tmp_a.*, MAX(tmp_b.goods_date) AS last_date FROM 
		( SELECT id,goods_code,goods_date,goods_price FROM test_goods_price_change WHERE goods_price IS NOT NULL AND goods_date IS NOT NULL ) AS tmp_a
		LEFT JOIN
		( SELECT id,goods_code,goods_date,goods_price FROM test_goods_price_change WHERE goods_price IS NOT NULL AND goods_date IS NOT NULL ) AS tmp_b
		ON tmp_a.goods_code = tmp_b.goods_code AND tmp_a.goods_date > tmp_b.goods_date GROUP BY tmp_a.id
	) AS tmp_ab 
	LEFT JOIN (SELECT id,goods_code,goods_date,goods_price FROM test_goods_price_change WHERE goods_price IS NOT NULL AND goods_date IS NOT NULL ) AS tmp_c
	ON tmp_ab.goods_code = tmp_c.goods_code AND tmp_c.goods_date = tmp_ab.last_date ORDER BY tmp_ab.id
) AS tmp

到此这篇关于仅用一句SQL更新整张表的涨跌幅、涨跌率的文章就介绍到这了,更多相关SQL更新整张表内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
Mysql 如何批量插入数据
Apr 06 MySQL
详解MySQL的半同步
Apr 22 MySQL
MySQL8.0.18配置多主一从
Jun 21 MySQL
QT连接MYSQL数据库的详细步骤
Jul 07 MySQL
MySQL 如何限制一张表的记录数
Sep 14 MySQL
浅谈MySQL函数
Oct 05 MySQL
MySQL中CURRENT_TIMESTAMP的使用方式
Nov 27 MySQL
MYSQL如何查看进程和kill进程
Mar 13 MySQL
mysql中DCL常用的用户和权限控制
Mar 31 MySQL
mysql 乱码 字符集latin1转UTF8
Apr 19 MySQL
MySQL数据库事务的四大特性
Apr 20 MySQL
MySQL数据库配置信息查看与修改方法详解
Jun 25 MySQL
MySQL创建高性能索引的全步骤
将图片保存到mysql数据库并展示在前端页面的实现代码
MySQL的join buffer原理
Apr 29 #MySQL
Mysql服务添加 iptables防火墙策略的方案
Apr 29 #MySQL
MySQL数据迁移相关总结
MySQL慢查询的坑
解决MySQL存储时间出现不一致的问题
Apr 28 #MySQL
You might like
杏林同学录(六)
2006/10/09 PHP
PHP 和 XML: 使用expat函数(三)
2006/10/09 PHP
Yii2使用swiftmailer发送邮件的方法
2016/05/03 PHP
PHP中利用sleep函数实现定时执行功能实现代码
2016/08/25 PHP
更正确的asp冒泡排序
2007/05/24 Javascript
利用jQuery操作对象数组的实现代码
2011/04/27 Javascript
jQuery之选择组件的深入解析
2013/06/19 Javascript
js登录弹出层特效
2014/03/07 Javascript
jQuery学习笔记之jQuery原型属性和方法
2014/06/09 Javascript
深入理解javascript构造函数和原型对象
2014/09/23 Javascript
百度地图自定义控件分享
2015/03/04 Javascript
微信中一些常用的js方法汇总
2015/03/12 Javascript
javascript截取字符串小结
2015/04/28 Javascript
深入讲解AngularJS中的自定义指令的使用
2015/06/18 Javascript
html5+CSS 实现禁止IOS长按复制粘贴功能
2016/12/28 Javascript
js时间控件只显示年月
2017/01/08 Javascript
js blob类型url的视频下载问题的解决
2019/11/29 Javascript
JavaScript中的类型检查
2020/02/03 Javascript
vuecli3.x中轻松4步带你使用tinymce的步骤
2020/06/25 Javascript
Vue+Java+Base64实现条码解析的示例
2020/09/23 Javascript
python中正则表达式的使用详解
2014/10/17 Python
Python封装shell命令实例分析
2015/05/05 Python
Python Paramiko模块的安装与使用详解
2016/11/18 Python
Python学习思维导图(必看篇)
2017/06/26 Python
Python探索之自定义实现线程池
2017/10/27 Python
Python socket实现多对多全双工通信的方法
2019/02/13 Python
对Python中小整数对象池和大整数对象池的使用详解
2019/07/09 Python
python二维键值数组生成转json的例子
2019/12/06 Python
pytorch GAN生成对抗网络实例
2020/01/10 Python
Python通过Schema实现数据验证方式
2020/11/12 Python
viagogo法国票务平台:演唱会、体育比赛、戏剧门票
2017/03/27 全球购物
兰蔻法国官方网站:Lancôme法国
2020/02/22 全球购物
C语言笔试题回忆
2015/04/02 面试题
测试时代收集的软件测试面试题
2013/09/25 面试题
劳资员岗位职责
2013/11/11 职场文书
意外伤害赔偿协议书
2014/09/16 职场文书