TopN,窗口函数(row_number, rank, dense_rank)实战

(求TopN)求出每种爱好中,年龄最大的两个人(姓名,爱好,年龄)

四个字段的意思:
id,姓名,年龄,爱好

表名topn
字段id, name, age, favors

1,ngxiaoming,45,a-c-d-f
2,huangzitao,36,b-c-d-e
3,huanglei,41,c-d-e
4,liushishi,22,a-d-e
5,liudehua,39,e-f-d
6,liuyifei,35,a-d-e

用到关键技术:
虚拟视图leteral view、explode、窗口函数row_number()


  1. 需要把favor字段进行拆分,拆成多行一列的值
    比如6,liuyifei,35,a-d-e拆成:
    6,liuyifei,35,a
    6,liuyifei,35,d
    6,liuyifei,35,e

  2. 使用explode进行拆分

    select explode(split("a-d-e","-"));
    

    在这里插入图片描述
    无法直接写sql语句进行favors的拆分,所以需要借助虚拟视图
    在这里插入图片描述

  3. 借助虚拟视图使用CTAS创建一张topn1表
    语法:lateral view utdf(表达式) 虚拟表名 as 虚拟表的列名,生成一张虚拟表。utdf函数通常把explode和split结合使用,针对from的表(如这里是topn表)的每一行进行操作。

    create table topn1 as select id,name,age,favortable.favor from topn
    lateral view explode(split(favors,"-")) favortable as favor;
    

    在这里插入图片描述

  4. 求出每种爱好的年龄最大的前2名
    分析:(一般既要分组又要排序,就要想到窗口函数)
    给topn1表弄一个排名,按爱好进行降序排序,然后选取每种爱好的前2名即可。

    窗口函数 row_number() 排序,排名相同编号也往后顺位

    select name,favor,age,
    row_number() over(partition by favor order by age desc) as index
    from topn1;
    

    在这里插入图片描述

  5. 求排名前2个记录
    因为where的执行顺序要先于窗口函数,无法直接使用条件index<=2。必须在外面再套一层select。

    select c.name,c.favor,c.age from (
    select name,favor,age,row_number() over(partition by favor order by age desc) as index 
    from topn1) as c 
    where c.index <=2;
    

    在这里插入图片描述
    窗口函数-排序-区别

    row_number() 排序,排名相同编号也往后顺位
    rank() 排序,排名相同编号一样,跳过空位,比如4后直接到6
    dense_rank() 排序,排名相同编号一样,不跳过空位,比如4后接着到5
    在这里插入图片描述
    当排名一样的时候,选排名前2,可能是2个人,也可能3个人,所以需要按实际需求选择用哪个排序函数。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章