自连接,窗口函数(sum、avg、max、min)实战

采用自连接窗口函数两种方法解题:

求每个用户截止到每月为止的当月访问次数、最大单月访问次数、累计到该月的总访问次数。

三个字段的意思:
用户名,月份,访问次数

表名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,自连接

  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
    
  2. 根据上述语句用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
    
  3. 我们需要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;
    

    结果:
    在这里插入图片描述

  4. 求最大访问次数和总访问次数。
    最大访问次数:当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
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章