我们在写Sql语句的时候没经常会遇到将查询结果列转行,例如做vintage报表的时候,SqlServer中有了PIVOT/UNPIVOT函数可以快速实现行转列和列转行的操作,然而hive中没有,大多数人都是通过写一系列的case when函数来实现,个人觉得使用case when这种方法虽然很好,但是很繁琐,这里抛砖引玉一下,通过使用窗口函数来实现列转换操作。
废话不说,直接上表,说明咱们需要处理的问题:
表 1 | ||
---|---|---|
月份 | 期数 | 金额 |
2019/01 | 1 | 1000000 |
2019/01 | 2 | 1100000 |
2019/01 | 3 | 1200000 |
2019/02 | 1 | 1400000 |
2019/02 | 2 | 1000000 |
2019/02 | 3 | 1500000 |
表 2 | |||
月份 | 期数1_金额 | 期数2_金额 | 期数3_金额 |
2019/01 | 1000000 | 1100000 | 1200000 |
2019/02 | 1400000 | 1000000 | 1500000 |
我们需要将表1格式的数据转换成表2格式的数据,就是我们将要解决的列转行问题,大多数人使用case when 实现,这里我们使用窗口函数中的lead()函数实现,lead(column,n)获取当前数据行按照某种排序规则的下n行数据的某个字段。
假定你已经建好了表test_table,包含date、term、jine这3个字段,插入数据:
insert into test_table values('2019/01', '1','1000000');
insert into test_table values('2019/01', '2','1100000');
insert into test_table values('2019/01', '3','1200000');
insert into test_table values('2019/02', '1','1400000');
insert into test_table values('2019/02', '2','1000000');
insert into test_table values('2019/02', '3','1500000');
select date, term1_jine, term2_jine, term3_jine
from
(select date, jine term1_jine,
lead(jine,1) over(partition by date order by term) term2_jine,
lead(jine,2) over(partition by date order by term) term3_jine,
row_number() over(partition by date order by term) row_num
from test_table) a
where row_num = 1
或者
select date, jine term1_jine,
lead(jine,1) over(partition by date order by term) term2_jine,
lead(jine,2) over(partition by date order by term) term3_jine,
row_number() over(partition by date order by term) row_num
from test_table
having row_num = 1
(需要说明一下,有些数据库环境不支持这样写哦)
这样你就可以得到表2格式的数据啦。顺便说一下,在你做vintage报表的时候,也可以使用这样的方法实现你的需求哦。
说一点点废话哈,经常使用sql的童鞋,建议把窗口函数学一下,可以实现很多复杂的任务,有时间的话,我会继续写一下日常使用窗口函数解决复杂的问题的。