问题场景

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

复现场景

表:主键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更新整张表的涨跌幅、涨跌率的更多相关文章

  1. Azure SQL Database (21) 将整张表都迁移到Azure Stretch Database里

    <Windows Azure Platform 系列文章目录>  Azure SQL Database (19) Stretch Database 概览      Azure SQL Da ...

  2. Django项目:CRM(客户关系管理系统)--41--33PerfectCRM实现King_admin编辑整张表限制

    readonly_table=False#默认表单不锁定 readonly_table=True#默认表单不锁定 # forms.py # ————————19PerfectCRM实现King_adm ...

  3. Oracle两张表关联批量更新其中一张表的数据

    Oracle两张表关联批量更新其中一张表的数据 方法一(推荐): UPDATE 表2 SET 表2.C = (SELECT B FROM 表1 WHERE 表1.A = 表2.A) WHERE EXI ...

  4. Mysql InnoDB行锁不使用索引锁表的时候会锁整张表

    原文:http://www.thinkphp.cn/topic/41577.html 如果使用针对InnoDB的表使用行锁,被锁定字段不是主键,也没有针对它建立索引的话.行锁锁定的也是整张表.锁整张表 ...

  5. (转) 【oracle调优】优化全表扫---cache整张表或索引

    情景分析: 1)某查询必须要走全表扫描 2)该查询执行的频率相当高 3)对执行时间的要求也相当苛刻的话 4)数据库的IO比较吃紧 5)数据库的内存比较宽松 6)该表的大小没有大到离谱 以上情况下,可以 ...

  6. SQL查询——同一张表的横向与纵向同时比较

    表名:student 表结构及数据: +----+--------+---------+------+------------+--------------+---------+ | id | nam ...

  7. 一条sql解决.一张表的数据复制到另外一张表

    如何把一个表的数组复制到一张表?也许很多人会把这个表查出来的数据再插入到另外一张表里面,这样很麻烦又要写代码逻辑去处理,其实一条sql语句就可以把一张表的数据复制到另外一张表,或者一张表的某一条数据复 ...

  8. sql 查出一张表中重复的所有记录数据

    1.在面试的时候碰到一个 问题,就是让写一张表中有id和name 两个字段,查询出name重复的所有数据,现在列下: select * from xi a where (a.username) in ...

  9. sql 对一张表进行按照不同条件进行多次统计

    最近一直在做数据统计,在此过程中,遇到过好多种情况都是对一张表按照不同的条件进行多次统计,以前的做法是统计几次按照不同的条件left join 几次,虽然也能得到想要的结果,但是效率太低,反映在页面就 ...

随机推荐

  1. 看完我的笔记不懂也会懂----AngulaJS

    目录 Angular.js学习笔记 ng-app(指令) ng-model ng-init angular之表达式 双向数据绑定 数据流向的总结 作用域对象 控制器对象 依赖对象与依赖注入 命令式与声 ...

  2. 后端程序员之路 42、Semaphore

    前面学习了Pthreads,了解了线程和线程同步,而同步这个东西,与信号量是密不可分的.下面讨论的主要是Pthreads里的semaphore.h,而不是sys/sem.h [Linux]线程同步之信 ...

  3. Vuex理解与使用

    1.Vuex是什么 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,用于管理页面的数据状态.提供统一数据操作的生态系统.在组件中可以任意获取仓库中的数据.和Vuex类似的还有redux ...

  4. MySQL:逻辑库与表管理

    逻辑库管理 语句 说明 CREATE DATABASE 逻辑库名; 创建逻辑库 SHOW DATABASES; 显示所有逻辑库 DROP DATABASE 逻辑库名; 删除逻辑库 USE 逻辑库名; ...

  5. WIFI6 基本知识(一)

    什么是WI-FI6(802.11ax) Wi-Fi 6 是下一代 802.11ax 标准的简称.随着 Wi-Fi 标准的演进,WFA 为了便于 Wi-Fi 用户和设备厂商轻松了解其设备连接或支持的 W ...

  6. C#关于个Base64,MD5,16进制的转换

    1,待签名数据以UTF-8的格式转字节流,对字节流进行MD5算法得到的签名字节流,再转换为16进制字符串,即生成了数字签名. byte[] targetData = md5.ComputeHash(S ...

  7. JAVA -JSON-XML-MAP转换

      //定义一个MAP对象,将对象传给后端接口接收 Map a = ["api": '11', ZGUID: "1231",BESKZ: "1231& ...

  8. 爬虫必知必会(7)_scrapy框架高级

    一.请求传参 实现深度爬取:爬取多个层级对应的页面数据 使用场景:爬取的数据没有在同一张页面中 在手动请求的时候传递item:yield scrapy.Request(url,callback,met ...

  9. 深入理解Java并发框架AQS系列(一):线程

    深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 一.概述 1.1.前言 重剑无锋,大巧不工 读j.u.c包下的源码,永远无法绕开的经典 ...

  10. 前端学习 node 快速入门 系列 —— 服务端渲染

    其他章节请看: 前端学习 node 快速入门 系列 服务端渲染 在简易版 Apache一文中,我们用 node 做了一个简单的服务器,能提供静态资源访问的能力. 对于真正的网站,页面中的数据应该来自服 ...