环比,表示连续2个单位周期(比如连续两月)内的量的变化比,反映本期比上期增长了多少; 计算公式:环比增长率=(本期数-上期数)/上期数×100%,例如某商城2018年2月份销售额比2018年1月份销售额增长了多少。
同比一般情况下是今年第n月与去年第n月比,用以说明本期发展水平与去年同期发展水平对比而达到的相对发展速度,计算公式:同比增长速度=(本期发展水平-去年同期水平)/去年同期水平×100%,例如某商城2019年1月份比2018年1月份销售额增长了多少等。
使用sql计算环比和同比的时候,查看了大多数人都是通过表嵌套表计算环比和同比,这里同样,我们使用几行简单的窗口函数来计算环比和同比。
构造一些数据集,例如,下面是某公司在不同地区,不同省份的销售额:
日期 | 地区 | 省份 | 销售额 |
2017/12 | 华东 | 上海市 | 3600000 |
2017/12 | 华东 | 江苏省 | 2800000 |
2017/12 | 华东 | 浙江省 | 4500000 |
2017/12 | 华北 | 北京市 | 3000000 |
2017/12 | 华北 | 天津市 | 2800000 |
2018/01 | 华东 | 上海市 | 3000000 |
2018/01 | 华东 | 江苏省 | 2000000 |
2018/01 | 华东 | 浙江省 | 2500000 |
2018/01 | 华北 | 北京市 | 2600000 |
2018/01 | 华北 | 天津市 | 1500000 |
2018/02 | 华东 | 上海市 | 3500000 |
2018/02 | 华东 | 江苏省 | 2100000 |
2018/02 | 华东 | 浙江省 | 2400000 |
2018/02 | 华北 | 北京市 | 2800000 |
2018/02 | 华北 | 天津市 | 2000000 |
2018/03 | 华东 | 上海市 | 2900000 |
2018/03 | 华东 | 江苏省 | 2800000 |
2018/03 | 华东 | 浙江省 | 2900000 |
2018/03 | 华北 | 北京市 | 3500000 |
2018/03 | 华北 | 天津市 | 3000000 |
2018/04 | 华东 | 上海市 | 2900000 |
2018/04 | 华东 | 江苏省 | 3000000 |
2018/04 | 华东 | 浙江省 | 2800000 |
2018/04 | 华北 | 北京市 | 3000000 |
2018/04 | 华北 | 天津市 | 2500000 |
我们的需求是:
(1)求不同地区不同省份每个季节的环比是多少?
(2)求不同地区不同省份每个季节的同比是多少?
假定已经构建一个表明为new_table含有date、area、province和saleroom四个字段:date表示年度季节,area表示地区,province表示省份,saleroom表示销售额。插入数据:
insert into new_table values ('2017/12', '华东', '上海市', '3600000');
insert into new_table values ('2017/12', '华东', '江苏省', '2800000');
insert into new_table values('2017/12', '华东', '浙江省', '4500000');
insert into new_table values('2017/12', '华北', '北京市', '3000000');
insert into new_table values('2017/12', '华北', '天津市', '2800000');
insert into new_table values('2018/01', '华东', '上海市', '3000000');
insert into new_table values('2018/01', '华东', '江苏省', '2000000');
insert into new_table values('2018/01', '华东', '浙江省', '2500000');
insert into new_table values('2018/01', '华北', '北京市', '2600000');
insert into new_table values('2018/01', '华北', '天津市', '1500000');
insert into new_table values('2018/02', '华东', '上海市', '3500000');
insert into new_table values('2018/02', '华东', '江苏省', '2100000');
insert into new_table values('2018/02', '华东', '浙江省', '2400000');
insert into new_table values('2018/02', '华北', '北京市', '2800000');
insert into new_table values('2018/02', '华北', '天津市', '2000000');
insert into new_table values('2018/03', '华东', '上海市', '2900000');
insert into new_table values('2018/03', '华东', '江苏省', '2800000');
insert into new_table values('2018/03', '华东', '浙江省', '2900000');
insert into new_table values('2018/03', '华北', '北京市', '3500000');
insert into new_table values('2018/03', '华北', '天津市', '3000000');
insert into new_table values('2018/04', '华东', '上海市', '2900000');
insert into new_table values('2018/04', '华东', '江苏省', '3000000');
insert into new_table values('2018/04', '华东', '浙江省', '2800000');
insert into new_table values('2018/04', '华北', '北京市', '3000000');
insert into new_table values('2018/04', '华北', '天津市', '2500000');
梳理思路:
计算环比:首先需要将不同地区不同省份的销售额按季节单位排需,然后计算连续2个单位周期销售额环比;
计算同比:首先需要将不同地区不同省份的销售额按年度单位排序,然后计算连续2个单位周期销售额同比;
两个共同的特点是:第一步:按照不同地区不同省份分组,按照时间进行排序,第二步:将相邻的两行进行计算,所有可以使用窗口函数lead()函数实现。
环比计算:
select date, area, province, saleroom,
lead(saleroom,1) over(partition by area, province order by date desc) lead_saleroom
provinfrom provincnew_table;
我们得到下表数据:
date | area | province | saleroom | lead_saleroom |
2018/04 | 华东 | 上海市 | 2900000 | 2900000 |
2018/03 | 华东 | 上海市 | 2900000 | 3500000 |
2018/02 | 华东 | 上海市 | 3500000 | 3000000 |
2018/01 | 华东 | 上海市 | 3000000 | 3600000 |
2017/12 | 华东 | 上海市 | 3600000 | NULL |
2018/04 | 华东 | 江苏省 | 3000000 | 2800000 |
2018/03 | 华东 | 江苏省 | 2800000 | 2100000 |
2018/02 | 华东 | 江苏省 | 2100000 | 2000000 |
2018/01 | 华东 | 江苏省 | 2000000 | 2800000 |
2017/12 | 华东 | 江苏省 | 2800000 | NULL |
2018/04 | 华东 | 浙江省 | 2800000 | 2900000 |
2018/03 | 华东 | 浙江省 | 2900000 | 2400000 |
2018/02 | 华东 | 浙江省 | 2400000 | 2500000 |
2018/01 | 华东 | 浙江省 | 2500000 | 4500000 |
2017/12 | 华东 | 浙江省 | 4500000 | NULL |
2018/04 | 华北 | 北京市 | 3000000 | 3500000 |
2018/03 | 华北 | 北京市 | 3500000 | 2800000 |
2018/02 | 华北 | 北京市 | 2800000 | 2600000 |
2018/01 | 华北 | 北京市 | 2600000 | 3000000 |
2017/12 | 华北 | 北京市 | 3000000 | NULL |
2018/04 | 华北 | 天津市 | 2500000 | 3000000 |
2018/03 | 华北 | 天津市 | 3000000 | 2000000 |
2018/02 | 华北 | 天津市 | 2000000 | 1500000 |
2018/01 | 华北 | 天津市 | 1500000 | 2800000 |
2017/12 | 华北 | 天津市 | 2800000 | NULL |
不同地区不同省份的环比为:(saleroom - lead_saleroom)/ lead_saleroom,所以最终代码为:
select *,
(saleroom - lead_saleroom)/lead_saleroom huanbi
from
(select date, area, city, saleroom,
lead(saleroom,1) over(partition by area, province order by date desc) lead_saleroom
from lianxi.new_table) t
where lead_saleroom is not null
得到环比:
date | area | province | saleroom | lead_saleroom | 环比 |
2018/04 | 华东 | 上海市 | 2900000 | 2900000 | 0.00% |
2018/03 | 华东 | 上海市 | 2900000 | 3500000 | -17.14% |
2018/02 | 华东 | 上海市 | 3500000 | 3000000 | 16.67% |
2018/01 | 华东 | 上海市 | 3000000 | 3600000 | -16.67% |
2018/04 | 华东 | 江苏省 | 3000000 | 2800000 | 7.14% |
2018/03 | 华东 | 江苏省 | 2800000 | 2100000 | 33.33% |
2018/02 | 华东 | 江苏省 | 2100000 | 2000000 | 5.00% |
2018/01 | 华东 | 江苏省 | 2000000 | 2800000 | -28.57% |
2018/04 | 华东 | 浙江省 | 2800000 | 2900000 | -3.45% |
2018/03 | 华东 | 浙江省 | 2900000 | 2400000 | 20.83% |
2018/02 | 华东 | 浙江省 | 2400000 | 2500000 | -4.00% |
2018/01 | 华东 | 浙江省 | 2500000 | 4500000 | -44.44% |
2018/04 | 华北 | 北京市 | 3000000 | 3500000 | -14.29% |
2018/03 | 华北 | 北京市 | 3500000 | 2800000 | 25.00% |
2018/02 | 华北 | 北京市 | 2800000 | 2600000 | 7.69% |
2018/01 | 华北 | 北京市 | 2600000 | 3000000 | -13.33% |
2018/04 | 华北 | 天津市 | 2500000 | 3000000 | -16.67% |
2018/03 | 华北 | 天津市 | 3000000 | 2000000 | 50.00% |
2018/02 | 华北 | 天津市 | 2000000 | 1500000 | 33.33% |
2018/01 | 华北 | 天津市 | 1500000 | 2800000 | -46.43% |
同样的操作可以计算同比,只需要按照年份排序即可:
select *,
(saleroom - lead_saleroom)/lead_saleroom tongbi
from
(select date, area, city, saleroom,
lead(saleroom,1) over(partition by area, province order by substr(date,1,4) desc) lead_saleroom
from lianxi.new_table) t
where lead_saleroom is not null
这里分享了使用窗口函数计算环比和同比,再次见识到了窗口函数的强大之处,后续我们分析一下使用窗口函数做vintage报表。