SQL优化 - 同比计算
记录一次SQL优化, 在计算同比的时候. 就太久没有写语句了, 能力在逐渐下滑, 思维也是, 感觉还是有点可怕的. 自从转业务以来, 就基本没有碰过代码这方面了. 甚至连 SQL 都开始要搜索了. 而我日常更多是让专业的开发来做, 我负责跟进度, 也不知道我这样存在的意义是否有价值. 正好又在弄BI, 然后呢根据过往经验, 处理逻辑还是尽量在后台处理好, 前台就直接展示即可.
有这样一个基础的算同比的需求, 分为两步. 一个是要对某字段进行合并, 然后基于合并再进行汇总和计算同比. 我的 1.0 版本是这样的.
1.0 临时表 + 2表连接
用的是 Sql Server
WITH A AS (
SELECT
CASE
WHEN AGENT IN ('AA', 'AAA') THEN 'AA'
WHEN AGENT IN ('BB', 'BBB') THEN 'BB'
WHEN AGENT IN ('CC', 'CCC') THEN 'CCC'
ELSE AGENT END AS 代理
, 品类
, 销售时间
, 数量
FROM AAAAA
WHERE 是否电商 = 1
AND 品类 IN ('A品类', 'B品类', 'C品类')
)
-- MAIN
-- 当月销量
SELECT
B.*
, C.当月销量 AS 同期19月销
FROM (
SELECT
A.代理
, A.品类
, SUM(A.数量) AS 当月销量
FROM A
WHERE 销售时间 >= DATEFROMPARTS(YEAR(GETDATE()),MONTH(GETDATE()), 1)
AND 销售时间 <= GETDATE()
GROUP BY 代理, 品类
) AS B
-- 19年同期销量
LEFT JOIN (
SELECT
代理
, 品类
, SUM(数量) AS 当月销量
FROM A
WHERE 销售时间 >= DATEFROMPARTS(2019, MONTH(GETDATE()), 1)
AND 销售时间 <= DATEFROMPARTS(2019, MONTH(GETDATE()), DAY(GETDATE())-1)
GROUP BY 代理, 品类
) AS C
ON B.代理 = C.代理 AND B.品类 = C.品类
ORDER BY B.当月销量 DESC
问题点
- 为了处理一个字段, 建了个临时查询, 相等于遍历了一整个表
- 算同比, 用到了 2个表 (当期, 同期) 进行拼接 (各自还执行了一次 group by )
- 代码冗余, 结构不清晰
对于计算同比这块, 其实结构是完全一样的, 只是 时间 不同而已, 那判断时间就可以了, 完全没必要用 Join 搞两张表.
2.0 用 Case when 时间 代替表 Join 算同比
WITH A AS (
SELECT
CASE
WHEN AGENT IN ('AA', 'AAA') THEN 'AA'
WHEN AGENT IN ('BB', 'BBB') THEN 'BB'
WHEN AGENT IN ('CC', 'CCC') THEN 'CCC'
ELSE AGENT END AS 代理
, 品类
, 销售时间
, 数量
FROM AAAAA
WHERE 是否电商 = 1
AND 品类 IN ('A品类', 'B品类', 'C品类')
)
-- MAIN
SELECT
代理
, 品类
, SUM(CASE WHEN
销售时间 BETWEEN DATEFROMPARTS(YEAR(GETDATE()),MONTH(GETDATE()), 1) AND GETDATE()
THEN 数量 ELSE 0 END) AS 当月销量
, SUM(CASE WHEN
销售时间 BETWEEN DATEFROMPARTS(2019, MONTH(GETDATE()), 1) AND DATEFROMPARTS(2019, MONTH(GETDATE()), DAY(GETDATE())-1)
THEN 数量 ELSE 0 END) AS 同期19年月销量
FROM A
GROUP BY 代理, 品类
ORDER BY 当月销量 DESC
问题点
- 是减少了查询, 极大优化了, 但 临时表 也是不必要的, 可以一步到位.
- 美中不足, 尚可再优化
3.0 将 Case when 结合 Group By 一步到位
sql server 很烦的一点是, 不能同级引用...
SELECT
CASE
WHEN AGENT IN ('AA', 'AAA') THEN 'AA'
WHEN AGENT IN ('BB', 'BBB') THEN 'BB'
WHEN AGENT IN ('CC', 'CCC') THEN 'CCC'
ELSE AGENT END AS 代理
, 品类
, SUM(CASE WHEN
销售时间 BETWEEN DATEFROMPARTS(YEAR(GETDATE()),MONTH(GETDATE()), 1) AND GETDATE()
THEN 数量 ELSE 0 END) AS 当月销量
, SUM(CASE WHEN
销售时间 BETWEEN DATEFROMPARTS(2019, MONTH(GETDATE()), 1) AND DATEFROMPARTS(2019, MONTH(GETDATE()), DAY(GETDATE())-1)
THEN 数量 ELSE 0 END) AS 同期19年月销量
FROM AAAAA
WHERE 是否电商 = 1
AND 品类 IN ('A品类', 'B品类', 'C品类')
GROUP BY 品类, CASE
WHEN AGENT IN ('AA', 'AAA') THEN 'AA'
WHEN AGENT IN ('BB', 'BBB') THEN 'BB'
WHEN AGENT IN ('CC', 'CCC') THEN 'CCC'
ELSE AGENT END
ORDER BY 当月销量 DESC
抽空还是要多练练, 这个很容易就忘掉了.
SQL优化 - 同比计算的更多相关文章
- 性能优化之永恒之道(实时sql优化vs业务字段冗余vs离线计算)
在项目中,随着时间的推移,数据量越来越大,程序的某些功能性能也可能会随之下降,那么此时我们不得不需要对之前的功能进行性能优化.如果优化方案不得当,或者说不优雅,那可能将对整个系统产生不可逆的严重影响. ...
- SQL优化案例—— RowNumber分页
将业务语句翻译成SQL语句不仅是一门技术,还是一门艺术. 下面拿我们程序开发工程师最常用的ROW_NUMBER()分页作为一个典型案例来说明. 先来看看我们最常见的分页的样子: WITH CTE AS ...
- sql 优化
1.选择最有效率的表名顺序(只在基于规则的优化器中有效): oracle的解析器按照从右到左的顺序处理 from 子句中的表名,from子句中写在最后的表(基础表driving table)将被最先处 ...
- SQL 优化总结
SQL 优化总结 (一)SQL Server 关键的内置表.视图 1. sysobjects SELECT name as '函数名称',xtype as XType FROM s ...
- (转)SQL 优化原则
一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用 系统提交实际应用后,随着数据库中数据的增加,系 ...
- SQL优化技巧
我们开发的大部分软件,其基本业务流程都是:采集数据→将数据存储到数据库中→根据业务需求查询相应数据→对数据进行处理→传给前台展示.对整个流程进行分析,可以发现软件大部分的操作时间消耗都花在了数据库相关 ...
- 【MySQL】SQL优化系列之 in与range 查询
首先我们来说下in()这种方式的查询 在<高性能MySQL>里面提及用in这种方式可以有效的替代一定的range查询,提升查询效率,因为在一条索引里面,range字段后面的部分是不生效的. ...
- 提高SQL查询效率(SQL优化)
要提高SQL查询效率where语句条件的先后次序应如何写 http://blog.csdn.net/sforiz/article/details/5345359 我们要做到不但会写SQL,还要做到 ...
- 基于Oracle的SQL优化(社区万众期待 数据库优化扛鼎巨著)
基于Oracle的SQL优化(社区万众期待数据库优化扛鼎巨著) 崔华 编 ISBN 978-7-121-21758-6 2014年1月出版 定价:128.00元 856页 16开 编辑推荐 本土O ...
- Oracle SQL 优化原则(实用篇)
由于SQL优化优化起来比较复杂,并且还受环境限制,在开发过程中,写SQL必须遵循以下几点原则: 1.Oracle 采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他Where ...
随机推荐
- DevExpress WPF 在RibbonControl的Header中添加搜索框
主要代码: <dxb:BarEditItem Name="txtSearch" EditHorizontalAlignment="Center"> ...
- 原根学习笔记+BSGS复习笔记
学原根发现拔山盖世算法忘光了,干脆一块儿写了吧. \(BSGS\) 算法 \(BSGS\) 算法,又名拔山盖世算法.北上广深算法.他解决的问题如下: 求解最小的可行的 \(k\),满足 \(a^k\e ...
- PADS无模命令总结表
无模命令总结表 1.C 补充格式,在内层负片设计时用来显示 Plane 层的焊盘及 Thermal.使用方法是,从键盘上输入 C 显示,再次输入 C 可去除显示. 2.D 打开/关闭当前层显示,使用方 ...
- 关于企业微信扫码登陆vue
关于企业微信扫码登陆vue 企业微信扫码登陆官方文档 采用的是第一种(构造独立窗口登录二维码) 对于前端来说就步骤就是 页面展示二维码 => 用户扫码登陆点击确定 => 确定之 ...
- docker - [01] docker入门
弱小和无知不是生存的障碍,傲慢才是. -- <三体> 一.相关链接 Docker官网:https://www.docker.com/ 文档地址:https://docs.docker.co ...
- linux系统升级/更新OpenSSL版本操作流程记录
问题描述:有时OpenSSL版本过老升级,或者需要更新OpenSSL版本 1.登录linux系统后输入openssl version 查看现在使用的版本 我的输入后版本信息为:OpenSSL 1.1. ...
- sql server 2017 STRING_AGG() 替代方案
SELECT @StuId='"'+STRING_AGG(Id,'","')+'"'FROM( SELECT 'a'+cast(Id as varchar) I ...
- 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
3月6日最新消息,阿里云通义千问官方宣布推出最新推理模型 QwQ-32B,这一模型仅有 32B 参数,但在效果上与拥有 671B 参数的 DeepSeek-R1 相媲美.如果你自己部署 DeepSee ...
- redmine 迁移后邮箱配置
https://blog.csdn.net/love8753/article/details/126380927 步骤一 修改配置文件 步骤二 redmine 页面配置信息 步骤一 修改配置文件 打开 ...
- [SWPUCTF 2021 新生赛]ez_unserialize
概括 这是一道PHP反序列化的CTF赛题,本意是想用这道题对PHP反序列化进行一定的学习. 过程 我们打开赛题,看看内容 没有发现什么东西,看看他的页面代码 根据他的提示,感觉是存在一个robots. ...