POSTGRESQL中如何利用SQL语句快速的进行同环比?

1. 引言

在数据驱动的时代,了解销售、收入或任何业务指标的同比和环比情况对企业决策至关重要。本文将深入介绍如何利用 PostgreSQL 和 SQL 语句快速、准确地进行这两种重要分析。

2. 数据准备

为了演示,假设我们有一张 sales 表,存储了销售数据,包括 date(日期)、product_id(产品ID)、revenue(收入)等字段。首先,确保数据准备工作:

CREATE TABLE sales (date DATE,product_id INT,revenue DECIMAL(10, 2)
);INSERT INTO sales VALUES('2020-01-01', 1, 400),('2020-01-02', 1, 300),('2020-01-01', 2, 3000),('2020-01-02', 2, 3200),('2022-01-01', 1, 500),('2022-01-02', 1, 600),('2022-01-01', 2, 1200),('2022-01-02', 2, 1900),('2023-01-01', 1, 1000),('2023-01-02', 1, 1200),('2023-01-01', 2, 800),('2023-01-02', 2, 900);

插入上述数据后,进行数据查询:

SELECT* 
FROMsales 
ORDER BYproduct_id,DATE;

查询结果如下:
1

3. 时间序列数据处理

处理时间序列数据是同比和环比分析的关键。确保日期字段以正确的数据类型存储:

ALTER TABLE sales
ALTER COLUMN date SET DATA TYPE DATE;

4. 同比分析

同比分析是比较同一时间段内不同年份数据的变化情况。

4.1 对两年的数据进行对比

比如我们现在想看各年的总收入和平均收入。

SELECTEXTRACT(YEAR FROM date) AS year,sum(revenue) as sum_revenue,count(revenue) as count_revenue,AVG(revenue) AS avg_revenue
FROM sales
GROUP BY year
ORDER BY year;

运行后,结果如下:
2

4.2 计算两年的差额和同比

不考虑日期不连续的情况,即销售数据在原始序列中是每年连续的,如数据源中的2022年和2023年收入数据。代码如下:

--计算同比
WITH yearly_revenue AS (SELECTEXTRACT(YEAR FROM date) AS year,sum(revenue) as year_total_revenue,AVG(revenue) AS year_avg_revenueFROM salesWHERE EXTRACT(YEAR FROM date) in (2022,2023)GROUP BY year
)
select 
year,
year_total_revenue,
year_avg_revenue,
lag(year_total_revenue) over (partition by null order by year ) as pre_year_total_revenue, --计算去年的收入
COALESCE(year_total_revenue - LAG(year_total_revenue) OVER (ORDER BY year) , 0) AS yoy_growth_value, --计算各年之间的收入差额
COALESCE((year_total_revenue - LAG(year_total_revenue) OVER (ORDER BY year)) / NULLIF(LAG(year_total_revenue) OVER (ORDER BY year), 0) * 100, 0) AS yoy_growth_rate, --计算两年之间的增长比例
lag(year_avg_revenue) over (partition by null order by year ) as pre_year_avg_revenue, --计算去年的平均收入
COALESCE((year_avg_revenue - LAG(year_avg_revenue) OVER (ORDER BY year)) / NULLIF(LAG(year_avg_revenue) OVER (ORDER BY year), 0) * 100, 0) AS yoy_avg_growth_rate --计算平均收入增长比例
from yearly_revenue;

运行上述代码后,可以直接进行计算收入的同比数据,上述代码考虑了去年收入为0和为null的情况,运行后结果如下:

3

考虑日期不连续的情况,即销售数据在原始序列中是每年连续的,如数据源中的2020年和2022年收入数据。代码如下:

WITH yearly_revenue AS (SELECTEXTRACT(YEAR FROM date) AS year,SUM(revenue) AS year_total_revenue,AVG(revenue) AS year_avg_revenueFROM salesGROUP BY year
)
SELECTcurrent_year.year,current_year.year_total_revenue,previous_year.year_total_revenue AS last_year_total_revenue,previous_year.year_avg_revenue AS last_year_avg_revenue,COALESCE(current_year.year_total_revenue - previous_year.year_total_revenue,0)   yoy_growth_value,COALESCE(current_year.year_total_revenue / nullif(previous_year.year_total_revenue,0)-1,0) * 100  yoy_growth_rate
--   ,CASE
--     WHEN previous_year.year_total_revenue IS NOT NULL THEN
--       (current_year.year_total_revenue - previous_year.year_total_revenue) / previous_year.year_total_revenue * 100
--     ELSE
--       NULL
--   END AS year_on_year_growth
FROMyearly_revenue current_year
LEFT JOINyearly_revenue previous_year ON current_year.year = previous_year.year + 1
-- WHERE 
-- 	previous_year.year_total_revenue is not null
ORDER BYcurrent_year.year;

运行代码后,结果如下:
4

4.3 细分后的同比计算

我们只需要将上述的代码进行简单的修改后,就可以统计细分到任意维度的同比计算。代码如下:

	WITH yearly_revenue AS (SELECTEXTRACT(YEAR FROM date) AS year,product_id,SUM(revenue) AS year_total_revenue,AVG(revenue) AS year_avg_revenueFROM salesGROUP BY year,product_id
)
SELECTcurrent_year.year,current_year.product_id,current_year.year_total_revenue,previous_year.year_total_revenue AS last_year_total_revenue,previous_year.year_avg_revenue AS last_year_avg_revenue,COALESCE(current_year.year_total_revenue - previous_year.year_total_revenue,0)   yoy_growth_value,COALESCE(current_year.year_total_revenue / NULLIF(previous_year.year_total_revenue, 0) - 1, 0) * 100  yoy_growth_rate
--   ,CASE
--     WHEN previous_year.year_total_revenue IS NOT NULL THEN
--       (current_year.year_total_revenue - previous_year.year_total_revenue) / previous_year.year_total_revenue * 100
--     ELSE
--       NULL
--   END AS year_on_year_growth
FROMyearly_revenue current_year
LEFT JOINyearly_revenue previous_year ON current_year.year = previous_year.year + 1 and current_year.product_id = previous_year.product_id
-- WHERE 
-- 	previous_year.year_total_revenue is not null
ORDER BYcurrent_year.year,current_year.product_id;

运行上述代码后,结果如下:
5

5. 环比分析

环比分析是比较相邻时间段的数据变化情况。

5.1 简单的日期环比计算

不考虑数据缺失的情况下,如果要对2023年product_id为1的产品进行环比计算,可以使用以下代码进行简单的环比计算:

SELECTdate,revenue,LAG(revenue) OVER (ORDER BY date) AS prev_revenue,(revenue - LAG(revenue) OVER (ORDER BY date)) / LAG(revenue) OVER (ORDER BY date) * 100 AS growth_rate
FROM sales
WHEREextract(year from date) in (2023) and product_id in (1);

筛选后的数据:
5.1.1

进行计算后的数据:
5.1.2

5.2 先聚合再进行环比计算

在不考虑日期缺失情况下,如果我们要计算2023年的收入环比,那么我们就需要先按照日期进行聚合,然后再进行环比计算。这里有两种方法,代码如下:

-- 计算写法1
WITH daily_revenue AS (SELECTdate,sum(revenue) as day_total_revenueFROM salesGROUP BY date
)
select 
*,
LAG(day_total_revenue) OVER (ORDER BY day_total_revenue) AS prev_revenue,
COALESCE((day_total_revenue - LAG(day_total_revenue) OVER (ORDER BY date)),0) day_growth_value,
COALESCE((day_total_revenue - LAG(day_total_revenue) OVER (ORDER BY date)) / LAG(day_total_revenue) OVER (ORDER BY date) * 100,0) AS day_growth_rate
from daily_revenue
WHERE EXTRACT(YEAR FROM date) in (2023);
#计算写法2
SELECTdate,sum(revenue),LAG(sum(revenue)) OVER (ORDER BY date) AS prev_revenue,COALESCE((sum(revenue) - LAG(sum(revenue)) OVER (ORDER BY date)),0) day_growth_value,COALESCE((sum(revenue) - LAG(sum(revenue)) OVER (ORDER BY date)) / LAG(sum(revenue)) OVER (ORDER BY date) * 100,0) AS growth_rate
FROM sales
WHEREextract(year from date) in (2023)group by date;

无论那个代码都可以,运行后结果如下:
5.2.1

5.3 考虑日期不连续的环比计算

然而在现实统计中,我们的日期往往是不连续的,因此可以考虑下面的思路:

  • 1、先按照所需维度进行如何;
  • 2、进行日期拼接和计算

代码如下:

-- 1.先聚合到指定维度		
WITH daily_revenue AS (SELECT DATE, SUM ( revenue )	AS day_total_revenue FROM sales GROUP BY DATE 
) 
-- 2.再进行拼接
SELECTcurrent_day.DATE,current_day.day_total_revenue,prev_day.day_total_revenue prev_day_total_revenue,COALESCE ( current_day.day_total_revenue - prev_day.day_total_revenue, 0 ) day_growth_value,COALESCE ( current_day.day_total_revenue / NULLIF ( prev_day.day_total_revenue, 0 ) - 1, 0 ) * 100 day_growth_rate  --处理异常情况
FROMdaily_revenue current_dayLEFT JOIN daily_revenue prev_day ON DATE_TRUNC( 'day', current_day.DATE ) = DATE_TRUNC( 'day', prev_day.DATE ) + INTERVAL '1 day' 
-- WHERE 
-- prev_day.day_total_revenue is not nullORDER BYDATE;

运行后,效果如下:
5.3.1

6. 性能优化技巧

数据库性能是关键,特别是在处理大量数据时。

-- 为 date 列创建索引
CREATE INDEX idx_date ON sales (date);
-- 向上方一样,采用视图
WITH daily_revenue AS (SELECT DATE, SUM ( revenue )	AS day_total_revenue FROM sales GROUP BY DATE 
) SELECT *
FROMdaily_revenue;

7. 注意事项与常见问题

数据规范性和异常值处理是关键。确保日期格式正确,避免数据异常对分析造成的影响。

8. 结语

本文介绍了在 PostgreSQL 中利用 SQL 进行同比和环比分析的方法。从数据准备到复杂场景下的 SQL 查询,每一步都经过详细解释和示例演示。这些技能不仅能提升数据分析效率,还能为业务决策提供重要支持。利用这些方法,你可以更加准确、快速地分析业务数据,为企业带来更大价值。

希望这篇文章能帮助你更好地利用 SQL 在 PostgreSQL 中进行同比和环比分析!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/191029.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【PyTorch】线性回归

文章目录 1. 代码实现1.1 一元线性回归模型的训练 2. 代码解读2.1. tensorboardX2.1.1. tensorboardX的安装2.1.2. tensorboardX的使用 1. 代码实现 波士顿房价数据集下载 1.1 一元线性回归模型的训练 import numpy as np import torch import torch.nn as nn from torch.ut…

[足式机器人]Part4 南科大高等机器人控制课 Ch00 课程简介

本文仅供学习使用 本文参考: B站:CLEAR_LAB 南科大高等机器人控制课 Ch00 课程简介 1. What is this course about?2. Tentative Schedule暂定时间表 1. What is this course about? Develop a solid foundation in robot modeling and control to co…

深度学习:什么是知识蒸馏(Knowledge Distillation)

1 概况 1.1 定义 知识蒸馏(Knowledge Distillation)是一种深度学习技术,旨在将一个复杂模型(通常称为“教师模型”)的知识转移到一个更简单、更小的模型(称为“学生模型”)中。这一技术由Hint…

亚马逊首席技术官2024年科技预测

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

二叉树遍历及应用

文章目录 前言构建二叉树前序遍历中序遍历后序遍历二叉树的结点个数二叉树的叶节点个数二叉树的高度二叉树第K层结点个数 前言 二叉树的遍历及应用主要是运用了递归、分治的思想。在这一篇文章,小编将介绍二叉树的前序遍历、中序遍历、后序遍历,求二叉树…

Fiddler抓包工具之fiddler设置手机端抓包

fiddler设置手机端抓包 安卓手机抓包 第一步:配置电脑和安卓的相关设置 1、手机和fiddler位于同一个局域网内;首先从fiddler处获取到ip地址和端口号: ,点击online,最后一行就是ip地址 2、路径:Tools》O…

【ASP.NET CORE】数据迁移 codefirst

已经写好实体类,使用add-migration生成数据迁移语句,注意如果项目中有多个dbcontext需要使用 -context 名称,指定下需要使用的dbcontext add-Migration Address -context mvcsqlcontext运行后会生成两个文件 2. 使用Update-Database语句更…

#Css篇:实现一个元素水平和垂直居中实现左右固定,中间自身适应布局 左侧固定 右侧自适应

实现一个元素水平和垂直居中 元素示例&#xff1a; <div class"container"><div class"centered-element">居中的内容</div> </div>flex布局 .container {display: flex;justify-content: center;align-items: center;height: …

Web自动化测试详解

做测试的同学们都了解&#xff0c;做Web自动化&#xff0c;我们主要用Selenium或者是QTP。 有的人可能就会说&#xff0c;我没这个Java基础&#xff0c;没有Selenium基础&#xff0c;能行吗&#xff1f;测试虽然属于计算机行业&#xff0c;但其实并不需要太深入的编程知识&…

力扣129. 求根节点到叶节点数字之和

递归 思路&#xff1a; 递归子问题&#xff1a; sum 左子树值 右子树值子树值 上一级值 * 10 当前节点值 int sum prevSum * 10 root->val; calcSum(root->left, sum) calcSum(root->right, sum); 终止条件&#xff1a; 如果节点为 nullptr&#xff0c;则值为…

C++学习之路(十六)C++ 用Qt5实现一个工具箱(为屏幕颜色提取功能增加一个点击复制的功能)- 示例代码拆分讲解

上篇文章&#xff0c;我们用 Qt5 实现了在小工具箱中添加了《颜色代码转换和屏幕颜色提取功能》功能。今天我们把屏幕颜色提取的功能再扩展一下&#xff0c;让它可以点击复制吧。下面我们就来看看如何来规划开发这样的小功能并且添加到我们的工具箱中吧。 老规矩&#xff0c;先…

【无标题】RTI-DDS实现C/S通信

RTI-DDS&#xff08;Real-Time Innovations Data Distribution Service&#xff09;是一款实时消息传递中间件&#xff0c;用于实现分布式系统中的实时数据传输和通信。使用RTI-DDS&#xff0c;可以实现Client-Server&#xff08;CS&#xff09;通信模式&#xff0c;该协议在车…

leetcode 12.2 每日一题 拼车(近双百解法,绝对通俗易懂)

1094. 拼车 车上最初有 capacity 个空座位。车 只能 向一个方向行驶&#xff08;也就是说&#xff0c;不允许掉头或改变方向&#xff09; 给定整数 capacity 和一个数组 trips , trip[i] [numPassengersi, fromi, toi] 表示第 i 次旅行有 numPassengersi 乘客&#xff0c; 接…

编译ubuntu kernel

下载kernel源码 sudo apt-get install linux-source 下载完成后&#xff0c;kernel源码位于/usr/src/ 。 编译ubuntu kernel make oldconfig make menuconfig make make modules_install make install

数字图像处理(实践篇)十三 数据增强之给图像添加噪声!

目录 一 涉及的函数 二 实践 一 涉及的函数 skimage.util.random_noise( ) skimage.util.random_noise(image, modegaussian, seedNone, clipTrue, **kwargs) 函数的功能&#xff1a;为浮点型图片添加各种随机噪声。 输入&#xff1a; ①image&#xff1a;输入图像&…

【C/C++笔试练习】公有派生、构造函数内不执行多态、抽象类和纯虚函数、多态中的缺省值、虚函数的描述、纯虚函数的声明、查找输入整数二进制中1的个数、手套

文章目录 C/C笔试练习选择部分&#xff08;1&#xff09;公有派生&#xff08;2&#xff09;构造函数内不执行多态&#xff08;3&#xff09;抽象类和纯虚函数&#xff08;4&#xff09;多态中的缺省值&#xff08;5&#xff09;程序分析&#xff08;6&#xff09;重载和隐藏&a…

【开箱即用】前后端同时开源!周末和AI用Go语言共同研发了一款笔记留言小程序!

大家好&#xff0c;我是豆小匠。 真的是当你在怀疑AI会不会取代人类的时候&#xff0c;别人已经用AI工具加速几倍的生产速度了… 周末体验了和AI共同开发的感受&#xff0c;小项目真的可以一人全干了… 本次实验使用的AI工具有两个&#xff1a;1. GitHub Copilot&#xff08;…

ubuntu 更换国内镜像

备份 cd /etc/aptcp sources.list sources.list.bakup修改源为清华源 sed -i s/archive.ubuntu.com/mirrors.aliyun.com/g sources.list更新软件源 apt-get update其他源如下&#xff1a; mirrors.ustc.edu.cn 中科大 mirrors.163.com 163 mirrors.aliyun.com 阿里云

前端文本省略号后面添加复制文字

前端文本省略号后面添加复制文字 1、效果图 2、代码展示 <div class"link-content-wrap" click"copyLinkText"><div class"link-content">{{ shareResult.url || }} </div><span class"show-ellipsis" click&…

高防CDN技术的崛起与网络安全的演进

随着互联网的普及和网络攻击的不断升级&#xff0c;保障网站的稳定性和安全性成为了企业和个人关注的焦点。高防CDN&#xff08;Content Delivery Network&#xff09;作为一种网络安全解决方案&#xff0c;在近年来迅猛发展&#xff0c;为用户提供了强大的防御能力。本文将从高…