仅用一句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 相关文章推荐
left join、inner join、right join的区别
Apr 05 MySQL
MySQL 数据丢失排查案例
May 08 MySQL
Mysql基础知识点汇总
May 26 MySQL
MySQL下使用Inplace和Online方式创建索引的教程
May 26 MySQL
详细谈谈MYSQL中的COLLATE是什么
Jun 11 MySQL
Mysql案例刨析事务隔离级别
Sep 25 MySQL
一文带你探究MySQL中的NULL
Nov 11 MySQL
mysql5.7的安装及Navicate长久免费使用的实现过程
Nov 17 MySQL
MySQL图形化管理工具Navicat安装步骤
Dec 04 MySQL
MySQL sql模式设置引起的问题
May 15 MySQL
Mysql中mvcc各场景理解应用
Aug 05 MySQL
MySQL性能指标TPS+QPS+IOPS压测
Aug 05 MySQL
MySQL创建高性能索引的全步骤
将图片保存到mysql数据库并展示在前端页面的实现代码
MySQL的join buffer原理
Apr 29 #MySQL
Mysql服务添加 iptables防火墙策略的方案
Apr 29 #MySQL
MySQL数据迁移相关总结
MySQL慢查询的坑
解决MySQL存储时间出现不一致的问题
Apr 28 #MySQL
You might like
PHP 记录访客的浏览信息方法
2018/01/29 PHP
php实例化一个类的具体方法
2019/09/19 PHP
Javascript 面向对象 重载
2010/05/13 Javascript
js列举css中所有图标的实现代码
2011/07/04 Javascript
使用jquery实现图文切换效果另加特效
2013/01/20 Javascript
JQuery实现表格中相同单元格合并示例代码
2013/06/26 Javascript
javascript仿php的print_r函数输出json数据
2013/09/13 Javascript
javascript中clone对象详解
2014/12/03 Javascript
浅谈JavaScript中数组的增删改查
2016/06/20 Javascript
javascript简单写的判断电话号码实例
2017/05/24 Javascript
vue实现底部菜单功能
2018/07/24 Javascript
js序列化和反序列化的使用讲解
2019/01/19 Javascript
Node.js系列之发起get/post请求(2)
2019/08/30 Javascript
vue prop属性传值与传引用示例
2019/11/13 Javascript
实现vuex原理的示例
2020/10/21 Javascript
[02:43]DOTA2亚洲邀请赛场馆攻略——带你走进东方体育中心
2018/03/19 DOTA
[46:20]TFT vs Secret Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
[05:26]TI10典藏宝瓶套装外观展示
2020/07/03 DOTA
python中精确输出JSON浮点数的方法
2014/04/18 Python
Python画图学习入门教程
2016/07/01 Python
Python计算两个日期相差天数的方法示例
2017/05/23 Python
Python实现将文本生成二维码的方法示例
2017/07/18 Python
python使用zip将list转为json的方法
2018/12/31 Python
Python3中lambda表达式与函数式编程讲解
2019/01/14 Python
python隐藏终端执行cmd命令的方法
2019/06/24 Python
Django xadmin开启搜索功能的实现
2019/11/15 Python
Python 实现PS滤镜中的径向模糊特效
2020/12/03 Python
amazeui树节点自动展开折叠面板并选中第一个树节点的实现
2020/08/24 HTML / CSS
英国鲜花速递:Serenata Flowers
2018/04/03 全球购物
The Body Shop美体小铺西班牙官网:天然化妆品
2019/06/21 全球购物
Under Armour安德玛意大利官网:美国高端运动科技品牌
2020/01/16 全球购物
进程的查看和调度分别使用什么命令
2015/03/25 面试题
党员自我批评与反省材料
2014/02/10 职场文书
监察建议书格式
2014/05/19 职场文书
公安领导班子四风问题个人整改措施思想汇报
2014/10/09 职场文书
中学总务处工作总结
2015/08/12 职场文书