Hive中提供了越來越多的分析函數,用於完成負責的統計分析。
今天簡單整理一下,以務以后自己快速查詢,也給看到的朋友作個參考。
分析函數主要用於實現分組內所有和連續累積的統計。
一. AVG,MIN,MAX,和SUM
如果不指定ROWS BETWEEN,默認為從起點到當前行;
如果不指定ORDER BY,則將分組內所有值累加;
關鍵是理解ROWS BETWEEN含義,也叫做WINDOW子句:
PRECEDING:往前
FOLLOWING:往后
CURRENT ROW:當前行
UNBOUNDED:起點,UNBOUNDED PRECEDING 表示從前面的起點, UNBOUNDED FOLLOWING:表示到后面的終點
二. NTILE,ROW_NUMBER,RANK,DENSE_RANK
1) NTILE
NTILE(n),用於將分組數據按照順序切分成n片,返回當前切片值
NTILE不支持ROWS BETWEEN,比如 NTILE(2) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND CURRENT ROW)
如果切片不均勻,默認增加第一個切片的分布
2)ROW_NUMBER
ROW_NUMBER() –從1開始,按照順序,生成分組內記錄的序列,比如,按照pv降序排列,生成分組內每天的pv名次。
ROW_NUMBER() 的應用場景非常多,再比如,獲取分組內排序第一的記錄;獲取一個session中的第一條refer等。
3)RANK和DENSE_RANK
RANK() : 生成數據項在分組中的排名,排名相等會在名次中留下空位
DENSE_RANK() : 生成數據項在分組中的排名,排名相等會在名次中不會留下空位
三. CUME_DIST,PERCENT_RANK
1) CUME_DIST
CUME_DIST 小於等於當前值的行數/分組內總行數
比如,統計小於等於當前薪水的人數,所占總人數的比例
2) PERCENT_RANK
將當前行的值歸一化為0到1的值,其中全部(或者分組)的最大值對應1,最小值對應0,其他均勻分布在0到1之間。
四. LAG,LEAD,FIRST_VALUE,LAST_VALUE
1)LAG
LAG(col,n,DEFAULT) 用於統計窗口內往上第n行值
第一個參數為列名,第二個參數為往上第n行(可選,默認為1),第三個參數為默認值(當往上第n行為NULL時候,取默認值,如不指定,則為NULL)
2)LEAD
與LAG相反
LEAD(col,n,DEFAULT) 用於統計窗口內往下第n行值
第一個參數為列名,第二個參數為往下第n行(可選,默認為1),第三個參數為默認值(當往下第n行為NULL時候,取默認值,如不指定,則為NULL)
3)FIRST_VALUE
取分組內排序后,截止到當前行,第一個值,(如果不指定分組,則返回第一行的值)
4)LAST_VALUE
取分組內排序后,截止到當前行,最后一個值
如果不指定ORDER BY,則默認按照記錄在文件中的偏移量進行排序,會出現錯誤的結果
如果想要取分組內排序后最后一個值,則需要變通一下,用FIRST_VALUE函數,然后按指定的排序字段倒排。
五. GROUPING SETS,GROUPING_ID,CUBE,ROLLUP
這幾個分析函數通常用於OLAP中,不能累加,而且需要根據不同維度上鑽和下鑽的指標統計,比如,分小時、天、月的UV數。
1)GROUPING SETS
在一個GROUP BY查詢中,根據不同的維度組合進行聚合,等價於將不同維度的GROUP BY結果集進行UNION ALL
SELECT month, day, COUNT(DISTINCT cookieid) AS uv, GROUPING__ID FROM lxw1234 GROUP BY month,day GROUPING SETS (month,day,(month,day)) ORDER BY GROUPING__ID; month day uv GROUPING__ID ------------------------------------------------ 2015-03 NULL 5 1 2015-04 NULL 6 1 NULL 2015-03-10 4 2 NULL 2015-03-12 1 2 NULL 2015-04-12 2 2 NULL 2015-04-13 3 2 NULL 2015-04-15 2 2 NULL 2015-04-16 2 2 2015-03 2015-03-10 4 3 2015-03 2015-03-12 1 3 2015-04 2015-04-12 2 3 2015-04 2015-04-13 3 3 2015-04 2015-04-15 2 3 2015-04 2015-04-16 2 3 等價於 SELECT month,NULL,COUNT(DISTINCT cookieid) AS uv,1 AS GROUPING__ID FROM lxw1234 GROUP BY month UNION ALL SELECT NULL,day,COUNT(DISTINCT cookieid) AS uv,2 AS GROUPING__ID FROM lxw1234 GROUP BY day UNION ALL SELECT month,day,COUNT(DISTINCT cookieid) AS uv,3 AS GROUPING__ID FROM lxw1234 GROUP BY month,day
2)GROUPING__ID
其中的 GROUPING__ID,表示結果屬於哪一個分組集合
3)CUBE
根據GROUP BY的維度的所有組合進行聚合。
SELECT month, day, COUNT(DISTINCT cookieid) AS uv, GROUPING__ID FROM lxw1234 GROUP BY month,day WITH CUBE ORDER BY GROUPING__ID; month day uv GROUPING__ID -------------------------------------------- NULL NULL 7 0 2015-03 NULL 5 1 2015-04 NULL 6 1 NULL 2015-04-12 2 2 NULL 2015-04-13 3 2 NULL 2015-04-15 2 2 NULL 2015-04-16 2 2 NULL 2015-03-10 4 2 NULL 2015-03-12 1 2 2015-03 2015-03-10 4 3 2015-03 2015-03-12 1 3 2015-04 2015-04-16 2 3 2015-04 2015-04-12 2 3 2015-04 2015-04-13 3 3 2015-04 2015-04-15 2 3 等價於 SELECT NULL,NULL,COUNT(DISTINCT cookieid) AS uv,0 AS GROUPING__ID FROM lxw1234 UNION ALL SELECT month,NULL,COUNT(DISTINCT cookieid) AS uv,1 AS GROUPING__ID FROM lxw1234 GROUP BY month UNION ALL SELECT NULL,day,COUNT(DISTINCT cookieid) AS uv,2 AS GROUPING__ID FROM lxw1234 GROUP BY day UNION ALL SELECT month,day,COUNT(DISTINCT cookieid) AS uv,3 AS GROUPING__ID FROM lxw1234 GROUP BY month,day
4)ROLLUP
是CUBE的子集,以最左側的維度為主,從該維度進行層級聚合。
比如,以month維度進行層級聚合: SELECT month, day, COUNT(DISTINCT cookieid) AS uv, GROUPING__ID FROM lxw1234 GROUP BY month,day WITH ROLLUP ORDER BY GROUPING__ID; month day uv GROUPING__ID --------------------------------------------------- NULL NULL 7 0 2015-03 NULL 5 1 2015-04 NULL 6 1 2015-03 2015-03-10 4 3 2015-03 2015-03-12 1 3 2015-04 2015-04-12 2 3 2015-04 2015-04-13 3 3 2015-04 2015-04-15 2 3 2015-04 2015-04-16 2 3 可以實現這樣的上鑽過程: 月天的UV->月的UV->總UV
--把month和day調換順序,則以day維度進行層級聚合: SELECT day, month, COUNT(DISTINCT cookieid) AS uv, GROUPING__ID FROM lxw1234 GROUP BY day,month WITH ROLLUP ORDER BY GROUPING__ID; day month uv GROUPING__ID ------------------------------------------------------- NULL NULL 7 0 2015-04-13 NULL 3 1 2015-03-12 NULL 1 1 2015-04-15 NULL 2 1 2015-03-10 NULL 4 1 2015-04-16 NULL 2 1 2015-04-12 NULL 2 1 2015-04-12 2015-04 2 3 2015-03-10 2015-03 4 3 2015-03-12 2015-03 1 3 2015-04-13 2015-04 3 3 2015-04-15 2015-04 2 3 2015-04-16 2015-04 2 3 可以實現這樣的上鑽過程: 天月的UV->天的UV->總UV (這里,根據天和月進行聚合,和根據天聚合結果一樣,因為有父子關系,如果是其他維度組合的話,就會不一樣)
