背景
平常我们使用 hive或者 mysql时,一般聚合函数用的比较多。但对于某些偏分析的需求,group by可能很费力,子查询很多,这个时候就需要使用窗口分析函数了~
注:hive、oracle提供开窗函数,mysql8之前版本不提供,但Oracle发布的 MySQL 8.0版本支持窗口函数(over)和公用表表达式(with)这两个重要的功能!

 

问题1

有一个订单表A,分别有order_id(订单id)、user_id(用户id)、amt(金额)三个字段,用sql实现以下功能:

i. 求订单总量为top3的用户及交易笔数。

ii. 求每个用户top3交易金额的订单。

iii. 求订单总量从大到小排名在50%之前的用户。

select user_id,total_amt,nums from (

select count(*) nums,sum(amt) as total_amt,user_id from a group by user_id

) t order by total_amt desc limit 3;

 

select user_id,amt from (

select row_number() over(partition by user_id order by amt desc) rn,user_id,amt from a

) t where rn <= 3;

 

select total_amt,user_id from (

select percent_rank() over(order by t.total_amt desc rows between unbounded preceding and unbounded following) ratio,total_amt,user_id from (

select count(*) nums,sum(amt) as total_amt,user_id from a group by user_id

) t

) t1 where ratio >= 0.5;

 

问题2

以下表记录了用户每天的充值流水记录。

table_name:user_topup

seq(key) user_id data_dt topup_amt

流水号 用户 日期 充值金额(元)

xxxxx01 u_001 2017/1/1 10

xxxxx02 u_001 2017/1/2 150

xxxxx03 u_001 2017/1/2 110

xxxxx04 u_001 2017/1/2 10

xxxxx05 u_001 2017/1/4 50

xxxxx06 u_001 2017/1/4 10

xxxxx07 u_001 2017/1/6 45

xxxxx08 u_001 2017/1/6 90

xxxxx09 u_002 2017/1/1 10

xxxxx10 u_002 2017/1/2 150

xxxxx11 u_002 2017/1/2 70

xxxxx12 u_002 2017/1/3 30

xxxxx13 u_002 2017/1/3 80

xxxxx14 u_002 2017/1/4 150

xxxxx14 u_002 2017/1/5 101

xxxxx15 u_002 2017/1/6 68

xxxxx16 u_002 2017/1/6 120

统计累计充值金额最多的top10用户,并计算每个用户比他后一名多充值多少钱。

select total_topup_amt,user_id,total_topup_amt - follow[1] as diff from (

select total_topup_amt,user_id,collect_list(total_topup_amt) over(rows between 1 preceding and 1 following) follow from (

select sum(topup_amt) as total_topup_amt,user_id from a group by user_id

) as t order by total_topup_amt desc limit 10

) as tt

 

问题3

用一条SQL 语句 查询出每门课程都小于80分的学生姓名和他的平均分。

name column1 column2

张三 语文 81

张三 数学 75

李四 语文 76

李四 数学 65

王五 语文 81

王五 数学 100

王五 英语 90

select name,avg(column2) as avg_score from score group by name having max(column2) < 80

 

附录 

select name,class,score,sum(score)over(order by score range between 2 preceding and 2 following) mm from student;
adf         3        45         45  --45加2减2即43到47,但是s在这个范围内只有45
asdf       3        55         55
cfe         2        74         74
3dd        3        78        158 --78在76到80范围内有78,80,求和得158
fda         1        80        158
gds        2        92         92
ffd          1        95         190
dss        1        95         190
ddd        3        99         198
gf           3        99         198