一、窗口函数

定义:窗口 + 函数,在执行函数时,定义一个窗口(函数执行的范围)

  1. over()没有order by 和wind子句,默认上下无边界(有分区上下边界为分区大小)
  2. 分区和分组的区别
    group by会去重,开窗函数中partition by 不会去重
  3. over()有order by 没有window子句默认窗口大小是上无边界到当前行
    window子句里面的含义:
  4. 排名函数 lead lag over中不需要跟window子句
CURRENT ROW:当前行
 n PRECEDING:往前n行数据
 n FOLLOWING:往后n行数据
 UNBOUNDED:起点,UNBOUNDED PRECEDING 表示从前面的起点, UNBOUNDED FOLLOWING表示到后面的终点

统计表中字段

name,orderdate,cost
jack,2017-01-01,10
tony,2017-01-02,15
jack,2017-02-03,23
tony,2017-01-04,29
jack,2017-01-05,46
jack,2017-04-06,42
tony,2017-01-07,50
jack,2017-01-08,55
mart,2017-04-08,62
mart,2017-04-09,68

1、标准聚集函数

MAX、MIN、AVG、COUNT、SUM

sum用法

需求0:查询在2017年4月份购买过的顾客及总人数

select name,count(*) over(rows between  UNBOUNDED PRECEDING and UNBOUNDED  FOLLOWING)
from business
where year(orderdate)=2017 and month(orderdate)=4
group by name
或
select name,count(*) over()
from business
where year(orderdate)=2017 and month(orderdate)=4
group by name

需求1:查询顾客的购买明细及月购买总额
错误求法:不能求出明细

select name,substring(orderdate,1,7),sum(cost)
from business
group by  name,substring(orderdate,1,7)

正确求法
学习点

  1. over()没有order by 和wind子句,默认上下无边界(有分区上下边界为分区大小)
  2. 分区和分组的区别
    group by会去重,开窗函数中partition by 不会去重
select name,orderdate,cost,sum(cost) over(partition by name,substring(orderdate,1,7)  )
from business

需求2:查询顾客每月的购买明细,将cost按照日期进行累加
学习点
3. over()有order by 没有window子句默认窗口大小是上无边界到当前行

select name,orderdate,cost,sum(cost) over(partition by name,substring(orderdate,1,7) 
order by orderdate  )
from business

2、专门的窗口函数

LEAD: LEAD  (列名 [,offset] [,default])
	 取后offset行的数据,如果没取到,用default代替.		
	 要求必须window必须是上下均无边界								
LAG: LAG  (列名 [,offset] [,default]) 
	取前offset行的数据,如果没取到,用default代替
FIRST_VALUE: FIRST_VALUE(列名,[是否跳过null值])
	获取指定列在窗口中的第一个值,可以传入第二个参数为boolean类型,默认为       false,代表是否跳过null值!
LAST_VALUE:LAST_VALUE(列名,[是否跳过null值])

lag用法

需求3:查看顾客的明细和上次的购买时间

select name,orderdate,cost,lag(orderdate,1,'无数据') over(partition by name 
order by orderdate  )
from business

lead用法

需求4:查看顾客的明细和下一笔的购买时间
学习点
要求窗口是上无边界到下无边界

select name,orderdate,cost,lead(orderdate,1,'无数据') over(partition by name 
order by orderdate rows between UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING  )
from business

FIRST_VALUE用法

需求5:查询每个顾客每月明细和第一笔订单时间

select name,orderdate,cost,FIRST_VALUE(orderdate,true) over(partition by name,substring(orderdate,1,7)
order by orderdate  )
from business

LAST_VALUE用法

需求6:查询每个顾客每月明细和最后一笔订单时间
学习点
要求必须window必须是上下均无边界

select name,orderdate,cost,LAST_VALUE(orderdate,true) over(partition by name,substring(orderdate,1,7)
order by orderdate  rows between UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING )
from business

需求7:查看顾客的消费明细,以及最近三笔消费总额
方法一:

①当前一笔+之前最近两笔
select name,orderdate,cost,cost
+lag(cost,1,0) over(partition by name order by orderdate  )
+lag(cost,2,0) over(partition by name order by orderdate  )
from business

或
select name,orderdate,cost,sum(cost) over(partition by name order by orderdate
rows between 2 PRECEDING and current row   )
from business

3、统计排名函数

RANK:   允许重复,如果有并列,就跳号!
ROW_NUMBER:连续
DENSE_RANK: 允许重复,如果有并列,不跳号!
CUME_DIST:  当前分数之前的总人数(包括当前分数) / 数据集总人数
PERCENT_RANK: rank-1 / 数据集总人数-1
NTILE(n): 将数据均分到n组中,返回当前数据的组号

需求:查询前20%时间的订单信息// 前x%,就使用cume_dist

select name,orderdate,cost
from
(select name,orderdate,cost, CUME_DIST() over(order by orderdate ) cd
from business) tmp
where cd <=0.2

或
select name,orderdate,cost
from
(select name,orderdate,cost,ntile(5) over(order by orderdate ) n
from business) tmp
where n =1

排名函数练习

// 按照科目进行排名
select  name,subject,score, rank() over(partition by subject order by score desc) rk
from score

// 给每个学生的总分进行排名
select  name,sum(score)  ,rank() over(order by  sum(score) desc) rk
from score
group by name

// 只查询每个科目的成绩的前2名
select * from
(select  name,subject,score, rank() over(partition by subject order by score desc) rk
from score) tmp
where rk <=2

//查询学生成绩,并显示当前科目最高分
select  name,subject,score,FIRST_VALUE(score,true) over(partition by subject order by score desc) maxscore
from score

//查询学生成绩,并显示当前科目最低分
select  name,subject,score,FIRST_VALUE(score,true) over(partition by subject order by score ) maxscore
from score

或
select  name,subject,score,LAST_VALUE(score,true) over(partition by subject order by score desc 
rows between current row and UNBOUNDED FOLLOWING) minscore
from score

二、日期函数

year(2017-04-11)
month(2017-04-11)
date_format(‘2019-02-15’,‘yyyy-MM’);
date_add(‘2019-02-15’,-1);
datediff:两个日期相差的天数,前-后
next_day(‘2019-02-12’,‘MO’); 得到下一个周的周一的日期
last_day(‘2019-02-15’); 得到本月的最后一天的日期

三、UDTF函数(列转行)

lateral view:lateral view explode(category) table_tmp as category_name
explode(列名):将hive一列中复杂的array或者map结构拆分成多行
原表

《疑犯追踪》	悬疑,动作,科幻,剧情
《Lie to me》	悬疑,警匪,动作,心理,剧情
《战狼2》	战争,动作,灾难

目标数据

《疑犯追踪》      悬疑
《疑犯追踪》      动作
《疑犯追踪》      科幻
《疑犯追踪》      剧情
《Lie to me》   悬疑
《Lie to me》   警匪
《Lie to me》   动作
《Lie to me》   心理
《Lie to me》   剧情
《战狼2》        战争
《战狼2》        动作
《战狼2》        灾难
select
    movie,
    category_name
from 
    movie_info lateral view explode(category) table_tmp as category_name;

四、拼接函数(行转列)

concat(constellation, “,”, blood_type) :返回n个字符串的拼接结果!如果有一个参数为null,返回null
concat_ws(’|’, collect_set(t1.name)):使用分隔符拼接传入的字符串和字符串数组中的字符串,会跳过分隔符参数后的任何 NULL 和空字符串!
collect_set(col):函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型字段
collect_list(col):跟上面函数的区别为不去重

原表

孙悟空	白羊座	A
大海	     射手座	A
宋宋	     白羊座	B
猪八戒    白羊座	A
凤姐	     射手座	A

目标数据

射手座,A            大海|凤姐
白羊座,A            孙悟空|猪八戒
白羊座,B            宋宋
select
    t1.base,
    concat_ws('|', collect_set(t1.name)) name
from
    (select
        name,
        concat(constellation, ",", blood_type) base
    from
        person_info) t1
group by
    t1.base;

五、常用函数

  1. get_json_object
  2. substring(列明,1,7) 截取数据(从第几位开始刦,截多少位)
  3. 除去空字段赋值(nvl(value,default_value))
  4. case when then else end

没有克服不了的困难,只有畏惧的心。 生活之所以耀眼,是因为磨难与辉煌会同时出现。所以,别畏惧暂时的困顿,即使无人鼓掌,也要全情投入,优雅坚持。请相信:不管多险峻的高山,总会给勇敢的人留一条攀登的路。只要你肯迈步,路就会在你脚下延伸。