impalasql和hivesql的窗口函数和根据月份时间增量取数

窗口函数和根据月份时间增量取数

今天跟大家分享一下窗口函数
举个例子:假设当前环境为impala,
drop table if exists dw.stu;
----dw库中的stu表-------------------
create table dw.stu(
fperiod string comment’年月’,
name string comment’姓名’,
age int comment’年龄’,
salary double comment’薪资’,
bonus double comment’奖金‘,
)
partitioned by (dt_month string)
comment’工资表’
row format delimited fields terminated by ‘\001’
stored as parquet;
—以上是建表语句-------------------------------------------------------

–完成增量取数(增加上一个月的数据进来)------------------------
–方法一
insert overwrite table dw.stu partition (dt_month) --此处因为我们用月份分区,所以可以使用insert overwrite,不会覆盖以前的数据,指挥覆盖上月数据,这不影响数据的最终结果。
select
fperiod --年月
,name --姓名
,age --年龄
,salary --薪资
,bonus --奖金
,sum(bonus) as bonus --科目费用
,fperiod as dt_month
from dm.stu_base --数据源表
where is_it = 1
and fperiod=concat(substr(to_date(add_months(trunc(current_timestamp(),‘MM’),-1)),1,4) --对时间戳的年份进行编辑 ,substr(to_date(add_months(trunc(current_timestamp(),‘MM’),-1)),6,2)) --这里是用concat对字符串进行了拼接,(转为string类型(to_date可以不像是00:00:00(增月(截取(当前时间戳(),‘月’),-1取上个月)),第6个字符,取2位))
group by fperiod
,name
,age
,salary;
–向表中插入数据-----------------------------------------------------------
insert overwrite table dw.stu_per partition (dt_month) --插入数据到dw.stu_per表,按照dt_month分区
select
a.fperiod --年月
,a.name --姓名
,a.age --年龄
,a.salary --薪资
,a.bonus --奖金
, a.bonus_per ----奖金占全部奖金的比例
,a.fperiod as dt_mont
from (select
fperiod --年月
,name --姓名
,age --年龄
,salary --薪资
,bonus --奖金
,bonus/sum(bonus) over(partition by fperiod, name,age,salary order by fperiod) as bonus_per --奖金占全部奖金的比例,聚合奖金字段,根据年月,姓名,年龄,薪资为维度。如果sum(bonus) over(),就是聚合全部。
,row_number() over(partition by fperiod, name,age,salary order by fperiod, name,age) as cc
from dw.stu) a
where a.cc = 1;

窗口函数的说明:

你还可以使用窗口函数OVER内的ORDER BY来控制行的顺序。 (ORDER BY窗口甚至不需要与行的输出顺序相匹配。)下面是一个例子:

SELECT depname, empno, salary,
rank() OVER (PARTITION BY depname ORDER BY salary DESC)
FROM empsalary;
depname | empno | salary | rank
-----------±------±-------±-----
develop | 8 | 6000 | 1
develop | 10 | 5200 | 2
develop | 11 | 5200 | 2
develop | 9 | 4500 | 4
develop | 7 | 4200 | 5
personnel | 2 | 3900 | 1
personnel | 5 | 3500 | 2
sales | 1 | 5000 | 1
sales | 4 | 4800 | 2
sales | 3 | 4800 | 2
————————————————

如果我们添加ORDER BY子句,我们会得到不同的结果:

SELECT salary, sum(salary) OVER (ORDER BY salary) FROM empsalary;
salary | sum
--------±------
3500 | 3500
3900 | 7400
4200 | 11600
4500 | 16100
4800 | 25700
4800 | 25700
5000 | 30700
5200 | 41100
5200 | 41100
6000 | 47100
这里的总和是从第一个(最低)工资到当前一个,包括任何当前重复的(注意重复薪金的结果)

执行窗口计算后,如果有必要对行进行过滤或分组,你可以使用子查询。例如:

SELECT depname, empno, salary, enroll_date
FROM
(SELECT depname, empno, salary, enroll_date,
rank() OVER (PARTITION BY depname ORDER BY salary DESC, empno) AS pos
FROM empsalary
) AS ss
WHERE pos < 3;
上面的查询只显示内部查询结果中rank小于3的行。

如果期待为多个窗口函数采用相同的窗口行为,这样做就会产生重复,并且容易出错。 作为代替,每个窗口行为可以在WINDOW子句中进行命名,然后再被OVER引用。 例如:

SELECT sum(salary) OVER w, avg(salary) OVER w
FROM empsalary
WINDOW w AS (PARTITION BY depname ORDER BY salary DESC);

截取时间戳的说明:

可以替换成下面这样:

and fperiod=replace(substr(to_date(add_months(trunc(current_timestamp(),‘MM’),-1)),1,7),’-’,’’) --取上个月数据,,’-’,’'是把前面的用‘’替换‘-’

还有可以先出了临时表,如下:

with t1 as(
select
a.fperiod
,concat(substring(a.fperiod,1,4),’-’,substring(a.fperiod,5,2),’-01’) as fperiod_new
,a.cost_branch_no
,a.cost_country_code
,a.acct_no
,sum(a.fifinal_amt) as fifinal_amt
,cast(a.fperiod as string) as dt_month
from dm.dm_cost_detail_edw_base a
where a.owner_type in (‘1’,‘7’)
and a.cost_branch_no=‘ITEL’
and a.is_hrbp<>1
and cast(a.fperiod as string)>=‘201901’ --初始化2019年1月数据
group by a.fperiod
,a.cost_branch_no
,a.cost_country_code
,a.acct_no)
select
t1.fperiod
,t1.cost_branch_no
,t1.cost_country_code
,t1.acct_no
,t1.fifinal_amt
,t1.dt_month
from t1
where t1.fperiod_new>=to_date(add_months(trunc(current_timestamp(),‘MM’),-1)) --上月月初
and t1.fperiod_new ;

你可能感兴趣的:(原创作者)