Hive SQL 求环比同比数据
Posted 千里之行,水落声声
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hive SQL 求环比同比数据相关的知识,希望对你有一定的参考价值。
前言
业务场景:原始表以天存储数据,以月维度统计数据及其对应的环比数据
历史时间环比:(上月数据-上上月数据)/上上月数据
当前时间环比:(当前时间数据-上月同期数据)/上月同期数据
上月同期概念:如今天是2023年3月26日,2023年3月的统计时间为3月1日-3月25日,故该时间区间的上月同期数据应为2023年2月1日-2月25日,而非整个2月
原始数据
表tmp存储每日数据,字段t_date为日期,t_value为测试值(可以是购买人数、访问量等任何有现实意义的数据),样例数据如图所示:
方法一
关键词:①一张表实现 ②add_months() ③date_add()
Step1:以月维度统计当月每天数据
难点:由上述上月同期概念可知,二月,作为当前月(三月)的环比月,不仅要保留整月数据作为二月当月的值,也要选取部分数据作为三月同期环比的值,靠字段t_month无法区分两种二月数据的差别,所以在group by时保留t_date
知识点:函数add_months(date,int),其中第一个参数为日期,第二个为按月增加的幅度
上月和同期两个条件通过add_months()实现,整体代码如下:
-- 每月数据
tmp2 as
(
-- 历月数据
select
substr(t_date,1,7) as t_month,
max(t_date) as t_date,
sum(t_value) as t_value
from tmp
group by substr(t_date,1,7)
union all
-- 上月同期数据
select
substr(t_date,1,7) as t_month,
max(t_date) as t_date,
sum(t_value) as t_value
from tmp
where substr(t_date,1,7)=substr(add_months(current_date(),-1),1,7) -- 上月
and t_date<=add_months(date_add(current_date(),-1),-1) -- 同期
group by substr(t_date,1,7)
)
汇总得到每月数据如图所示:
Step2:匹配环比数据,计算环比值。注意剔除上月同期数据
-- 方法一
select
t_month,
t_value,
hb_t_month,
hb_t_value,
case
when hb_t_value is null then null
else round((COALESCE(t_value,0)-COALESCE(hb_t_value,0))/COALESCE(hb_t_value,0),2)
end as hb
from
(select
t1.t_month as t_month,
t1.t_date as t_date,
t1.t_value as t_value,
t2.t_month as hb_t_month, -- 环比月
t2.t_date as hb_t_date, -- 环比日
t2.t_value as hb_t_value -- 环比值
from
tmp2 t1
left join
tmp2 t2
on add_months(t1.t_date,-1)=t2.t_date
) t
where t_date=add_months(date_add(concat(t_month,'-01'),-1),1) -- 剔除上月同期数据
or t_date=date_add(current_date(),-1) -- 保留当前月不被剔除
order by t_month desc
limit 10
得到结果如图所示:
注意点:假设current_date()为2023-03-31,当前月统计时间范围3月1日-3月30日,上月同期应为2月1日-2 月28日。
注意Step1,同期用了t_date<=add_months(date_add(current_date(),-1),-1),而不是t_date<add_months(current_date(),-1)。两者的区别如表所示:
语法 | 平常日current_date() 如2023-03-26 | 月末日current_date() 如2023-03-31 | 结论 |
t_date<= add_months (date_add(current_date(),-1),-1) | t_date<=’2023-02-25’ | t_date<=’2023-02-28’ | 平常日和月末日都能满足 |
t_date< add_months(current_date(),-1) | t_date<’2023-02-25’ | t_date<’2023-02-28’ | 平常日能满足,月末日无法满足 |
注意Step2,使用了t1.t_date=add_months(t2.t_date,1),而不是add_months(t1.t_date,-1)=t2.t_date。两者的区别如表所示:
语法 | 平常日 | 月末日 | 结论 |
t1.t_date=add_months(t2.t_date,1) | t2.t_date为2023-02-26,t1.t_date=add_months(‘2023-02-26’,1)=’2023-03-26’ | t2.t_date为2023-02-28,能匹配上2023-03-31,但是2023-03-30的数据将无法匹配 | 平常日能满足,月末日会丢失数据 |
add_months(t1.t_date,-1)=t2.t_date | t1.t_date为2023-03-26,t2.t_date=add_months(‘2023-03-26’,-1)=’2023-02-26’ | 无论t1.t_date为2023-03-31还是2023-03-30,都可以匹配上2023-02-28的数据 | 平常日和月末日都能满足 |
方法二
关键词:①同一张表② lead() over()
Step1 :同方法一的Step1
Step2 :知识点:开窗函数lead() over()。lead(expr,N,default)
expr:它可以是列或任何内置函数
N:正值,当前行向下偏移的行数,可忽略,默认值为1
default:函数返回的默认值,默认为NULL。当前行偏移N行后没有数据时显示。
-- 方法二
select
t_month,
t_value,
hb_t_value,
case
when hb_t_value is null then null
else round((COALESCE(t_value,0)-COALESCE(hb_t_value,0))/COALESCE(hb_t_value,0),2)
end as hb
from
(select
t1.t_month,
t1.t_date,
t1.t_value,
lead(t_value) over (order by t_month desc,t_date asc) as hb_t_value
from tmp2 t1
) t2
where t_date=add_months(date_add(concat(t_month,'-01'),-1),1) -- 剔除上月同期数据
or t_date=date_add(current_date(),-1) -- 保留当前月不被剔除
order by t_month desc
limit 10
方法三
关键词:①两张表
Step1:建一张历月数据表和一张环比月数据表,匹配环比数据,计算环比值。有别于方法一,这里可以直接用月进行匹配
-- 方法三
select
t.t_month,
t.t_value,
t_hb.t_month as hb_t_month,
t_hb.t_value as hb_t_value,
case
when t_hb.t_value is null then null
else round((COALESCE(t.t_value,0)-COALESCE(t_hb.t_value,0))/COALESCE(t_hb.t_value,0),2)
end as hb
from
-- 历月数据
(select
substr(t_date,1,7) as t_month,
max(t_date) as t_date,
sum(t_value) as t_value
from tmp
group by substr(t_date,1,7)
) t
left join
-- 环比月数据
(select
substr(t_date,1,7) as t_month,
max(t_date) as t_date,
sum(t_value) as t_value
from tmp
where t_date<=add_months(date_add(current_date(),-1),-1)
group by substr(t_date,1,7)
) t_hb
on t.t_month=substr(ADD_MONTHS(concat(t_hb.t_month,'-01'),1),1,7)
order by t.t_month desc
limit 10
求同比亦然,把add_months()中的1或-1改成12或-12即可
数据分析SQL环比增长率同比增长率
概念
环比
- month-on-month ratio
- 连续2个统计周期(比如连续两月)内的量的变化比
环比增长率
- chain growth rate
- 和上期相比较的增长率
-
环
比
增
长
率
=
(
本
期
数
−
上
期
数
)
÷
上
期
数
×
100
%
环比增长率=(本期数-上期数)\\div上期数\\times100\\%
环比增长率=(本期数−上期数)÷上期数×100%
或
环 比 增 长 率 = ( 本 期 数 ÷ 上 期 数 − 1 ) × 100 % 环比增长率=(本期数 \\div 上期数-1) \\times 100 \\% 环比增长率=(本期数÷上期数−1)×100%
同比
- on year-on-year basis
一般情况下是本年第n月与去年第n月比
同比增长率
YoY+%
- 一般是指和去年同期相比较的增长率
-
同
比
增
长
率
=
(
当
年
的
指
标
值
−
去
年
同
期
的
值
)
÷
去
年
同
期
的
值
×
100
%
同比增长率=(当年的指标值-去年同期的值)\\div去年同期的值\\times100\\%
同比增长率=(当年的指标值−去年同期的值)÷去年同期的值×100%
或
同 比 增 长 率 = ( 当 年 的 指 标 值 ÷ 去 年 同 期 的 值 − 1 ) × 100 % 同比增长率=(当年的指标值 \\div 去年同期的值-1) \\times 100 \\% 同比增长率=(当年的指标值÷去年同期的值−1)×100%
SQL(HIVE)
造数据
存在0以及缺失值的情况
CREATE VIEW sale(ym,sales) AS
SELECT '2020-01',1000 UNION ALL
SELECT '2020-02',800 UNION ALL
SELECT '2020-03',1200 UNION ALL
SELECT '2020-04',0 UNION ALL
SELECT '2020-05',1400 UNION ALL
SELECT '2020-06',1500 UNION ALL
SELECT '2020-07',NULL UNION ALL
SELECT '2020-08',1700 UNION ALL
SELECT '2020-09',1800 UNION ALL
SELECT '2020-10',1900 UNION ALL
SELECT '2020-11',3000 UNION ALL
SELECT '2020-12',2000 UNION ALL
SELECT '2021-01',1200 UNION ALL
SELECT '2021-02',1000 UNION ALL
SELECT '2021-03',1400 UNION ALL
SELECT '2021-04',800 UNION ALL
SELECT '2021-05',1300 UNION ALL
SELECT '2021-06',1200 UNION ALL
SELECT '2021-07',900 UNION ALL
SELECT '2021-08',700 UNION ALL
SELECT '2021-09',1000 UNION ALL
SELECT '2021-10',1800 UNION ALL
SELECT '2021-11',3200 UNION ALL
SELECT '2021-12',1500;
环比
SELECT
ym,
sales/LAG(sales,1,NULL) OVER (ORDER BY ym)-1 AS chain_growth_rate
FROM sale;
同比
SELECT
ym,
sales/LAG(sales,12,NULL) OVER (ORDER BY ym)-1 AS year_on_year_growth_rate
FROM sale;
以上是关于Hive SQL 求环比同比数据的主要内容,如果未能解决你的问题,请参考以下文章