0 前言
最近做数据分析,需要求每一组内的元素的百分比以及累计百分比,实在想不出怎么使用sql实现,就先将数据导出,然后使用excel计算。趁着夜深人静的时候,思维敏捷,尝试一下使用窗口函数实现一下,天佑我也,尝试了几次,最终成功了,这里分享一下,也算抛砖引玉,如果有更好的方法,可以共同交流一下。
1 需求描述
还是以往风格,直接用表格描述需求,虚构一些数据,某公司在每个地区不同月份的销售额如下:
我们需要在表1的后面加上3列:分别是组内百分比、组内累计值和组内累计百分比。
| 表 1 | ||
| 地区 | 年月 | 销售额 |
| A | 2018/04 | 1000000 |
| A | 2018/05 | 2000000 |
| A | 2018/06 | 1500000 |
| B | 2018/04 | 1000000 |
| B | 2018/05 | 1600000 |
| B | 2018/06 | 2000000 |
| B | 2018/07 | 1500000 |
| 表 2 | |||||
| 地区 | 年月 | 销售额 | 组内百分比 | 组内累积值 | 组内累积百分比 |
| A | 2018/04 | 1000000 | 22.22% | 1000000 | 22.22% |
| A | 2018/05 | 2000000 | 44.44% | 3000000 | 66.67% |
| A | 2018/06 | 1500000 | 33.33% | 4500000 | 100.00% |
| B | 2018/04 | 1000000 | 16.39% | 1000000 | 16.39% |
| B | 2018/05 | 1600000 | 26.23% | 2600000 | 42.62% |
| B | 2018/06 | 2000000 | 32.79% | 4600000 | 75.41% |
| B | 2018/07 | 1500000 | 24.59% | 6100000 | 100.00% |
2 需求实现
可以看出A地区3个月的销售总额为4500000,那么组内百分比分别为1000000/4500000、2000000/4500000和1500000/4500000,同理可以得到B地区的,但是在sql中怎么计算A地区和B地区的销售总额呢?可能你会想到group by一下地区,然后对每个地区销售额求和,可以求出来,但是个人觉得那样就比较繁琐了,写sql代码应该是一种享受的过程。这里我们使用窗口函数实现我们的需求:及加入一个字段sum(saleroom) over(partition by area order by area)即可。
组内累计和和组内累计百分比比较棘手,尝试了一些办法,分享一些认为比较简单的代码。
2.1 实现代码
为了呈现百分比的结果,我们使用round()函数以及concat()函数对小数结果进行处理,当然如果觉得输入结果为字符型,你也可以使用cast()函数进行转化格式:
sum(saleroom) over(partition by area order by date) ---求组内累计值
sum(saleroom) over(partition by area order by area) ---求组内总计值
select *,
sum(saleroom) over(partition by area order by date) aggregate_value,
sum(saleroom) over(partition by area order by area) total_vale
from WN_table1;
运行结果见表3:
| 表 3 组内累计值和组内总计 | ||||
| area | date | saleroom | aggregate_value | total_value |
| A | 2018/04 | 1000000 | 1000000 | 4500000 |
| A | 2018/05 | 2000000 | 3000000 | 4500000 |
| A | 2018/06 | 1500000 | 4500000 | 4500000 |
| B | 2018/04 | 1000000 | 1000000 | 6100000 |
| B | 2018/05 | 1600000 | 2600000 | 6100000 |
| B | 2018/06 | 2000000 | 4600000 | 6100000 |
| B | 2018/07 | 1500000 | 6100000 | 6100000 |
所以,
组内百分比= saleroom / total_value
累计百分比 = aggregate_value/total_value
故得到表2格式的代码如下:
select area, date, saleroom,
concat(round((saleroom /total_value)*100,2), '%') percent,
aggregate_value,
concat(round((aggregate_value/total_value)*100,2), '%') aggregate_percent
from
(select *,
sum(saleroom) over(partition by area order by date) aggregate_value,
sum(saleroom) over(partition by area order by area) total_value
from WN_table1
) t
3 总结
本文分享使用窗口函数实现一些复杂的需求,日后会陆续写一些有关窗口函数的内容,有时间的话,将窗口函数知识系列分享一些下,晚安,everyone。
