仅用一句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 使用事件(Events)完成计划任务
May 24 MySQL
MySQL为id选择合适的数据类型
Jun 07 MySQL
MySQL中IF()、IFNULL()、NULLIF()、ISNULL()函数的使用详解
Jun 26 MySQL
MySQL系列之九 mysql查询缓存及索引
Jul 02 MySQL
SQL IDENTITY_INSERT作用案例详解
Aug 23 MySQL
mysql主从复制的实现步骤
Oct 24 MySQL
MySQL笔记 —SQL运算符
Jan 18 MySQL
Mysql事务索引知识汇总
Mar 17 MySQL
简单聊一聊SQL注入及防止SQL注入
Mar 23 MySQL
MySQL的存储过程和相关函数
Apr 26 MySQL
MySQL查询日期时间
May 15 MySQL
MySQL普通表如何转换成分区表
May 30 MySQL
MySQL创建高性能索引的全步骤
将图片保存到mysql数据库并展示在前端页面的实现代码
MySQL的join buffer原理
Apr 29 #MySQL
Mysql服务添加 iptables防火墙策略的方案
Apr 29 #MySQL
MySQL数据迁移相关总结
MySQL慢查询的坑
解决MySQL存储时间出现不一致的问题
Apr 28 #MySQL
You might like
PHP 页面跳转到另一个页面的多种方法方法总结
2009/07/07 PHP
PHP遍历文件夹与文件类及处理类用法实例
2014/09/23 PHP
3种方法轻松处理php开发中emoji表情的问题
2016/07/18 PHP
JavaScript中关于indexOf的使用方法与问题小结
2010/08/05 Javascript
JQuery插件Style定制化方法的分析与比较
2012/05/03 Javascript
asp.net中oracle 存储过程(图文)
2015/08/12 Javascript
JavaScript的removeChild()函数用法详解
2015/12/27 Javascript
探究JavaScript中的五种事件处理程序方式
2016/12/07 Javascript
详解Node.js access_token的获取、存储及更新
2017/06/20 Javascript
NodeJS实现图片上传代码(Express)
2017/06/30 NodeJs
微信小程序实战篇之购物车的实现代码示例
2017/11/30 Javascript
浅析JS抽象工厂模式
2017/12/14 Javascript
AngularJS日期格式化常见操作实例分析
2018/05/17 Javascript
微信小程序时间轴实现方法示例
2019/01/14 Javascript
vue.js的vue-cli脚手架中使用百度地图API的实例
2019/01/21 Javascript
深入解析微信小程序开发中遇到的几个小问题
2020/07/11 Javascript
Python写的一个定时重跑获取数据库数据
2016/12/28 Python
Python3调用百度AI识别图片中的文字功能示例【测试可用】
2019/03/13 Python
python实现递归查找某个路径下所有文件中的中文字符
2019/08/31 Python
Pytorch maxpool的ceil_mode用法
2020/02/18 Python
使用HTML和CSS3绘制基本卡通图案的示例分享
2015/11/06 HTML / CSS
HTML5本地存储localStorage、sessionStorage基本用法、遍历操作、异常处理等
2014/05/08 HTML / CSS
Ticketmaster德国票务网站:购买音乐会和体育等门票
2016/11/14 全球购物
利物浦足球俱乐部官方网上商店:Liverpool FC Official Store
2018/01/13 全球购物
.net笔试题
2014/03/03 面试题
营销与策划个人求职信
2013/09/22 职场文书
汽车专业大学生职业生涯规划范文
2014/01/07 职场文书
女方回门宴答谢词
2014/01/14 职场文书
司法建议书范文
2014/05/13 职场文书
护理专业毕业生自荐信
2014/06/15 职场文书
另类冲刺标语
2014/06/24 职场文书
2014年销售部工作总结
2014/12/01 职场文书
2015年度员工自我评价范文
2015/03/11 职场文书
增值税发票丢失证明
2015/06/19 职场文书
2019军训心得体会
2019/06/27 职场文书
Redis Stream类型的使用详解
2021/11/11 Redis