仅用一句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 相关文章推荐
浅析InnoDB索引结构
Apr 05 MySQL
mysql的MVCC多版本并发控制的实现
Apr 14 MySQL
MySQL创建高性能索引的全步骤
May 02 MySQL
MySQL 视图(View)原理解析
May 19 MySQL
mysq启动失败问题及场景分析
Jul 15 MySQL
详细聊聊关于Mysql联合查询的那些事儿
Oct 24 MySQL
mysql5.6主从搭建以及不同步问题详解
Dec 04 MySQL
为什么MySQL不建议使用SELECT *
Apr 03 MySQL
MySQL库表太大怎么办? 数据库分库分表项目实践
Apr 11 MySQL
MySQL索引 高效获取数据的数据结构
May 02 MySQL
mysql拆分字符串作为查询条件的示例代码
Jul 07 MySQL
MySQL创建高性能索引的全步骤
将图片保存到mysql数据库并展示在前端页面的实现代码
MySQL的join buffer原理
Apr 29 #MySQL
Mysql服务添加 iptables防火墙策略的方案
Apr 29 #MySQL
MySQL数据迁移相关总结
MySQL慢查询的坑
解决MySQL存储时间出现不一致的问题
Apr 28 #MySQL
You might like
php异常处理技术,顶级异常处理器
2012/06/13 PHP
ThinkPHP表单自动验证实例
2014/10/13 PHP
详解PHP swoole process的使用方法
2017/08/26 PHP
PHP实现微信公众号验证Token的示例代码
2019/12/16 PHP
php设计模式之建造器模式分析【星际争霸游戏案例】
2020/01/23 PHP
彻底搞懂JS无缝滚动代码
2007/01/03 Javascript
某人初学javascript的时候写的学习笔记
2010/12/30 Javascript
js动态设置鼠标事件示例代码
2013/10/30 Javascript
基于Jquery实现键盘按键监听
2014/05/11 Javascript
jQuery对象的链式操作用法分析
2016/05/10 Javascript
JS加载器如何动态加载外部js文件
2016/05/26 Javascript
jQuery简单设置文本框回车事件的方法
2016/08/01 Javascript
JavaScript实现图片懒加载(Lazyload)
2016/11/28 Javascript
JavaScript数据结构中栈的应用之表达式求值问题详解
2017/04/11 Javascript
requirejs + vue 项目搭建详解
2017/06/16 Javascript
js+canvas实现滑动拼图验证码功能
2018/03/26 Javascript
详解vue更改头像功能实现
2019/04/28 Javascript
js定义类的方法示例【ES5与ES6】
2019/07/30 Javascript
vue 解决computed修改data数据的问题
2019/11/06 Javascript
详解JavaScript中的链式调用
2020/11/27 Javascript
Python中struct模块对字节流/二进制流的操作教程
2017/01/21 Python
Empty test suite.(PyCharm程序运行错误的解决方法)
2018/11/30 Python
解决python中画图时x,y轴名称出现中文乱码的问题
2019/01/29 Python
Python实现微信中找回好友、群聊用户撤回的消息功能示例
2019/08/23 Python
python中property属性的介绍及其应用详解
2019/08/29 Python
详解Python Opencv和PIL读取图像文件的差别
2019/12/27 Python
Python运行DLL文件的方法
2020/01/17 Python
Tensorflow获取张量Tensor的具体维数实例
2020/01/19 Python
互斥锁解决 Python 中多线程共享全局变量的问题(推荐)
2020/09/28 Python
英国最受信任的在线眼镜商之一:Fashion Eyewear
2019/10/31 全球购物
物业管理大学生个人的自我评价
2013/10/10 职场文书
服装公司总经理岗位职责
2013/11/30 职场文书
保密工作整改情况汇报
2014/11/06 职场文书
教师个人自我评价
2015/03/04 职场文书
2015年体育教学工作总结
2015/05/20 职场文书
经典《舰娘》游改全新动画预告 预定11月开播
2022/04/01 日漫