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個人,所以需要按實際需求選擇用哪個排序函數。

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