Hive 學習總結(jié)

? ? 這一周主要學習了 Hive 的一些基礎知識,學習了多個 Hive 窗口函數(shù),雖然感覺這些窗口函數(shù)沒有實際的應用意義,但還是都了解了一下。

sum()over()

:可以實現(xiàn)在窗口中實現(xiàn)逐行累加

其他 avg、count、min、max 的用法一樣

#要先有一個統(tǒng)計出每個月總額的表,這里就是 t_access_amount 表,如下圖一

# partition by uid:根據(jù)uid 分組,order by month :根據(jù)月份排序,

rows between unbounded preceding and current_row:選擇 無邊界的前面的行和當前行之間的行,最后是求 sum 即和。得到下圖二

# 是在窗口求和,而窗口的定義時按照 uid 分區(qū) order by 排序得到的。得到一個字段

select?uid,month,amount,

sum(amount)over(partition by uid order by month rows between unbounded preceding and??current_row )?as?accumulate?from?t_access_amount;

preceding:前面的,后來的,往序號變大的方向

following:往后

2 preceding :表示前2行

3 following :表示后3行

unbounded preceding:表示從第1行開始,從前面的起點

unbounded following:表示最后一行,從后面的終點

注意:使用 rows between 時,按order by 順序編號(沒有指定order by 會默認排序)需要左邊是小編號右邊是大編號

rows between unbounded following and current row??是錯的,應該寫作

rows between current row and unbounded following 是當前行到終點行

rows between current row and 1 preceding? ?也是錯的,應該寫作

rows between 1 preceding andcurrent row 表示前1行和當前行

select

???cookieid,

???createtime,

???pv,

? ?# 得到顯示的排序編號

? ?row_number() over(partition by cookieid order by createtime) as rn,

? ?# 從前面的起點到當前位置,這里是從分區(qū)最后一行到當前行的和

???sum(pv) over (partition by cookieid order by createtime rows between unbounded preceding and current row) as pv1,

? ?# 和上面一樣(加 order by 和不加效果不一樣)

???sum(pv) over (partition by cookieid order by createtime) as pv2,

#省略了 rows betweent 窗口函數(shù),表示分區(qū)的所有數(shù)據(jù)

???sum(pv) over (partition by cookieid) as pv3,

? ?# 前面3行+當前后

???sum(pv) over (partition by cookieid order by createtime rows between 3 preceding and current row) as pv4,

# 前面3行+當前行+后面1行

???sum(pv) over (partition by cookieid order by createtime rows between 3 preceding and 1 following) as pv5,

? ?# 當前行+后面所有行

???sum(pv) over (partition by cookieid order by createtime rows between current row and unbounded following) as pv6

from cookie1;


注意:上面顯示的排序結(jié)果不太對,所以看起來好像結(jié)果是相反的一樣,實際上單獨拿出來運行是對的,可以看以相同方式排序的 rn 編號。

2、row_numver()over()函數(shù)、NTILE、RANK、DENSE_RANK

注意:這上面這些都不支持使用 rows between 語句,row_number() 展示出來的排序會和查詢字段的最后一個 over(order by)里面的順序一樣

:分組?TOPN,即可以分組后排序,便于找到最好的幾條數(shù)據(jù)

eg:有如下數(shù)據(jù),要查出每種性別中年齡最大的2條數(shù)據(jù)

1,18,a,male

2,19,b,male

3,22,c,female

4,16,d,female

5,30,e,male

6,26,f,female

分析:如果使用按性別分組,是可以分出兩條數(shù)據(jù),但是分組的缺點是只能查出聚合函數(shù)(聚合函數(shù)只能產(chǎn)生一組中的一個值)和分組依據(jù)。而這里是要求多條數(shù)據(jù)(2個)

# 正確操作,這里先 partition by sex字段分組,然后根據(jù)每一組的 age 字段降序排序。得到的序號 1,2,3 等取名為 rn ,然后通過 where 判斷 前兩個就是結(jié)果

#?rn?字段是一個分組標記?序號,如下圖是中間(select ...)括號的結(jié)果

select * from

(select id,age,sex,row_number( ) over(partition by sex order by age desc)as rn from t_user)tmp

where rn<3;

NTILE(n)?

:用于將分組數(shù)據(jù)按照順序切分成 n 片(不一定是平均),然后每一份都編號為1-n,這樣就可以拿到想要那一份數(shù)據(jù)。如果切片不均勻,默認增加第一個切片的分布,例如,14 條記錄切3片就切不好,就會切成 6、4、4,其中6那份編號為1。

注意:可以不指定 order by

select

??cookieid,

??createtime,

??pv,

??ntile(2) over (partition by cookieid order by createtime) as rn2, --分組內(nèi)將數(shù)據(jù)分成2片

??ntile(3) over (partition by cookieid order by createtime) as rn3, --分組內(nèi)將數(shù)據(jù)分成3片

??ntile(4) over (order by createtime) as rn4 --將所有數(shù)據(jù)分成4片

from cookie2

order by cookieid,createtime;


應用:

? ? 統(tǒng)計各個 cookieid,pv 數(shù)最多的前1/3天的數(shù)據(jù)

select * from(

select *,ntile(3) over(partition by cookieid order by pv desc) as sn3 from cookie2) a where a.sn3=1;

RANK()

:生成數(shù)據(jù)項再分組中的排名,排名相等會在名次中留下空位

dense_rank()

:生成數(shù)據(jù)項再分組中的排名,排名相等不會再名次中留下空位

注意:上面兩者都需要指定 order by,不然排名都是1

select

??cookieid,

??createtime,

??pv,

??rank() over (partition by cookieid order by pv desc) as r1,

??dense_rank() over (partition by cookieid order by pv desc) as r2,

??row_number() over (partition by cookieid order by pv desc) as rn

from cookie.cookie2

where cookieid='cookie1';

根據(jù)上圖,可知區(qū)別:

? ? rank():按順序編號,相同分組排序有相同的排名,但是會占位,后面的排名隔一位,就是成績一樣名次相同,但是后面的名次得低兩位。

? ? dense_rank():按順序編號,相同分組排序有相同的排名,后面排名順序不邊就是有并列第幾名的情況。

? ? row_number() :按順序編號,不會有相同的編號,即使分組排序是相同的。

cume_dist

:小于等于當前值的行數(shù)/分組內(nèi)總行數(shù),注意這個要指定排序方式,不然全都是1

select?

? *,

? # 對 pv 降序排序后,計算小于等于當前行 pv 值得行數(shù)占總行數(shù)得比分

? cume_dist() over(order by pv) as rn1,

? # 計算cookieid 分組內(nèi),小于等于當前行 pv 值的行數(shù)占總行數(shù)的比分

? cume_dist() over(partition by cookieid order by pv) as rn2?

from cookie3;

percent_rank

:分組內(nèi)當前行的(rank 值-1)/(分組內(nèi)總行數(shù)-1)

select?

? * ,

? # 求得 rank 值

? rank() over(order by pv) as r1,

? # 求得總共有多少行,這里用 sum(1) 效果一樣

? count(1) over() as c1 ,

? # 得到的結(jié)果其實就是 rank -1/count(1) -1

? percent_rank() over(order by pv) as p1??

from cookie3;

總結(jié):排序、切片、編號、的都需要使用 order by,不然會全都是1,但是除了 row_number() 因為這個函數(shù)編號不重復且順延,所以還是會有編號,但是不確定編號邏輯。

lag

:用于獲得窗口內(nèi)往上第n行的值,n>=0

第一個參數(shù)為列名

第二個參數(shù)為往上第n行(可選,默認為1)

第三個參數(shù)為默認值(當往上第n行為NULL時,取默認值,如不指定,則為NULL)

# 就是用往上多少行的數(shù)據(jù)來替換當前行,可以為0,但是不能為負數(shù)

select

? ?*,

? ?row_number() over(partition by cookieid order by createtime) as r1,

? ?lag(createtime,1) over(partition by cookieid order by createtime) as la1,

? ?lag(createtime,2,'this is tidai') over(partition by cookieid order by createtime) as la2 from cookie4;

lead

:與lag 相反,用于獲取窗口內(nèi)往下第n 行的值,n>=0

第一個參數(shù)為列名

第二個參數(shù)為往上第n行(可選,默認為1)

第三個參數(shù)為默認值(當往上第n行為NULL時,取默認值,如不指定,則為NULL)

select

???*,

???row_number() over(partition by cookieid order by createtime) as r1,

???lead(createtime,1) over(partition by cookieid order by createtime) as la1,

???lead(createtime,2,'this is tidai') over(partition by cookieid order by createtime) as la2 from cookie4;

last_value

:取分組內(nèi)排序后,截止到當前行,最后一個值

first_value

:取分組內(nèi)排序后,第一個值

select?

? *,

? # 展示排序好像和最后一個 over 里面的 order by 有關

? row_number() over(partition by cookieid order by createtime) as r1,

? # 獲取最后一個值,但是其實都還是自己,因為只到當前行?

? last_value(url) over(partition by cookieid order by createtime) as l1,

# 轉(zhuǎn)換一下 order by 為desc,這樣第一個就是之前的最后一個,可以避免 rn 為1的寫法,但是如果有多個字段去重那還是取 rn=1 的方便些

? first_value(url) over(partition by cookieid order by createtime desc ) as f1 from cookie4;

注意:使用窗口分析函數(shù)時,要特別注意 order by 的使用,如果使用的不恰當會導致統(tǒng)計的不是我們想要的。row_number() over() 的展示排序好像時根據(jù)最后一個字段的over(order by)來展示的。

grouping sets 、grouping__id、cube、rollup

這幾個分析函數(shù)通常用于 olap 中,不能累加,而且需要根據(jù)不同維度上鉆和下鉆的指標統(tǒng)計,比如分 時、分、天、月的 UV 數(shù)

grouping__id

:表示結(jié)果屬于哪一個分組集合,注意中間是兩個下劃線

select?

? month ,

? day,

? count(distinct cookieid) as uv,

? GROUPING__ID?

from cookie5 group by month ,day?

grouping sets(month,day)?

order by GROUPING__ID;

第一列時按照 month 進行分組的,

第二列時按照 day 進行分組的

第三列時按照 對應month、day 分組統(tǒng)計出來的結(jié)果

第四列 grouping__id 表示這一組結(jié)果屬于哪個分組集合

注意:grouping sets 里面就是說明以什么分組,上面的group by 是指定可以進行組合的分組字段sets 里面的只能使用這里指定的字段,

如,這里 grouping sets(month , day) 表示分別根據(jù) month、day 字段分組,? ? ? ?? ? ? ??grouping sets(month,day,(month,day)) 則表示分別根據(jù) month、day、month和day 分組。??

這里group by 和 grouping sets 可以搭配使用,不是這里的專屬,并且這里也可以不用 groupind sets

select

??month ,

??day,

??count(distinct cookieid) as uv,

??GROUPING__ID

from cookie5 group by month ,day

grouping sets(month,day,(month,day))

order by GROUPING__ID;

# 上面的語句執(zhí)行結(jié)果等價于下面的

SELECT month,NULL,COUNT(DISTINCT cookieid) AS uv,1 AS GROUPING__IDFROM cookie5GROUP BY month

UNION ALL

SELECTNULL,day,COUNT(DISTINCT cookieid) AS uv,2 ASGROUPING__ID FROM cookie5GROUP BY day

UNION ALL

SELECT month,day,COUNT(DISTINCT cookieid) AS uv,3 ASGROUPING__ID FROM cookie5GROUP BY month,day

cube

:根據(jù)group by 的維度的所有組合進行聚合,就是省略 grouping sets ,直接將group by 后面的字段以各種可能的形式分組,然后union all 得到結(jié)果。

select?

? month,

? day,

? count(distinct cookieid) as uv,

? grouping__id?

from cookie5?

group by month,day?with cube

order by grouping__id;

等價于下面的語句

SELECTNULL,NULL,COUNT(DISTINCT cookieid) AS uv,0 AS GROUPING__ID FROM cookie5 -- 不分組

UNION ALL

SELECT month,NULL,COUNT(DISTINCT cookieid) AS uv,1 AS GROUPING__ID FROM cookie5GROUP BY month? --只對 month 分組

UNION ALL

SELECTNULL,day,COUNT(DISTINCT cookieid) AS uv,2 AS GROUPING__ID FROM cookie5GROUP BY day? --只對 day 分組

UNION ALL

SELECT month,day,COUNT(DISTINCT cookieid) AS uv,3 AS GROUPING__ID FROM cookie5GROUP BY month,day? -- 對 month、day 分組

rollup

:是 cube 的子集,以最左側(cè)的維度為主,從該維度進行層級聚合

# 是cube 的子集,以 month 為主,保留 month、month+day、不指定分組 三種情況

select?

? month,

? day,

? count(distinct cookieid) as uv ,

? grouping__id?

from cookie5?

group by month,day with rollup?

order by grouping__id;

上面可以實現(xiàn)一個叫上鉆的效果:

? ? 月天的uv==》月的uv==》總的uv

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容