采用自连接和窗口函数两种方法解题:
求每个用户截止到每月为止的当月访问次数、最大单月访问次数、累计到该月的总访问次数。
三个字段的意思:
用户名,月份,访问次数
表名visits
字段id, vmonth, pv
数据:
A,2015-01,5
A,2015-01,15
B,2015-01,5
A,2015-01,8
B,2015-01,25
A,2015-01,5
A,2015-02,4
A,2015-02,6
B,2015-02,10
B,2015-02,5
A,2015-03,16
A,2015-03,22
B,2015-03,23
B,2015-03,10
B,2015-03,11
最后结果展示:
结果数据 result-data (本月和上月比保留最大) (本月累加上月)
用户 月份 当月访问次数 最大访问次数 总访问次数
A 2015-01 33 33 33
A 2015-02 10 33 43
A 2015-03 38 38 81
B 2015-01 30 30 30
B 2015-02 15 30 45
B 2015-03 44 44 89
方法1,自连接
-
先求出当月访问次数
select id,vmonth,sum(pv) as pv from visits group by id,vmonth;
结果:
id vmonth pv A 2015-01 33 A 2015-02 10 A 2015-03 38 B 2015-01 30 B 2015-02 15 B 2015-03 44
-
根据上述语句用CTAS创建两张表t1和t2,用于自连接。
select * from v1 join v2 on v1.id = v2.id;
v1 v2 A 2015-01 33 A 2015-01 33 A 2015-02 10 A 2015-01 33 A 2015-03 38 A 2015-01 33 A 2015-01 33 A 2015-02 10 A 2015-02 10 A 2015-02 10 A 2015-03 38 A 2015-02 10 A 2015-01 33 A 2015-03 38 A 2015-02 10 A 2015-03 38 A 2015-03 38 A 2015-03 38 B 2015-01 30 B 2015-01 30 B 2015-02 15 B 2015-01 30 B 2015-03 44 B 2015-01 30 B 2015-01 30 B 2015-02 15 B 2015-02 15 B 2015-02 15 B 2015-03 44 B 2015-02 15 B 2015-01 30 B 2015-03 44 B 2015-02 15 B 2015-03 44 B 2015-03 44 B 2015-03 44
-
我们需要v2的月份>=v1的月份,用来后续做v1月份的累加操作。
create table v3 as select v1.id as v1id,v1.vmonth as v1month,v1.pv as v1pv, v2.id as v2id,v2.vmonth as v2month,v2.pv as v2pv from v1 join v2 on v1.id = v2.id where v2.vmonth >= v1.vmonth;
结果:
-
求最大访问次数和总访问次数。
最大访问次数:当v2的月份是1月时,对应v1只有1条记录,即为33
当v2的月份为2月时,对应v1有2条记录,最大访问为33
当v2的月份为3月时,对应v1有3条记录,最大访问为33
…
总访问次数:v1pv的累加
方法2:窗口函数(sum、avg、max、min)使用方法一致先求出当月访问次数
create table v1 as select id,vmonth,sum(pv) as pv from visits group by id,vmonth;
结果:
id vmonth pv A 2015-01 33 A 2015-02 10 A 2015-03 38 B 2015-01 30 B 2015-02 15 B 2015-03 44
select id,vmonth,pv, max(pv) over(partition by id order by vmonth rows between unbounded preceding and current row) as maxpv, sum(pv) over(partition by id order by vmonth rows between unbounded preceding and current row) as sumpv from v1;
解释:
【over】是窗口函数的关键字
【partition by】按照什么字段分区,可以理解为分组group by
【order by】排序,不写order by,表示分组内所有值相加
partition by 和 order by 配合使用 或者 distribute by 和 sort by 配合使用
(partition by 字段 order by 字段) 后面不跟范围条件,默认是从起点到当前行
【rows between a and b】行的范围条件,从a到b
【rows between unbounded preceding and current row】第一行+当前行
【unbounded preceding】最前面的起点(第一行)
【current row】当前行
【unbounded following】到后面的终点
【3 preceding】当前行+往前数3行
【1 following】当前行+往后数1行
【rows between 3 preceding and 1 following】当前行+往前数3行+往后数1行pv maxpv sumpv A 2015-01 33 33 33 A 2015-02 10 33 43 A 2015-03 38 38 81 B 2015-01 30 30 30 B 2015-02 15 30 45 B 2015-03 44 44 89