HIVE常用函數(1)聚合函數和序列函數


SUM--
sum(匯總字段) over (partition by 分組字段 order by 排序字段)

如果不指定ROWS BETWEEN,默認為從起點到當前行;
如果不指定ORDER BY,則將分組內所有值累加;
關鍵是理解ROWS BETWEEN含義,也叫做WINDOW子句:
PRECEDING:往前
FOLLOWING:往后
CURRENT ROW:當前行
UNBOUNDED:起點,

  UNBOUNDED PRECEDING 表示從前面的起點,

  UNBOUNDED FOLLOWING:表示到后面的終點
–其他AVG,MIN,MAX,和SUM用法一樣。

select 
   cookieid, 
   createtime, 
   pv, 
   sum(pv) over (partition by cookieid order by createtime rows between unbounded preceding and current row) as pv1, 
   sum(pv) over (partition by cookieid order by createtime) as pv2, 
   sum(pv) over (partition by cookieid) as pv3, 
   sum(pv) over (partition by cookieid order by createtime rows between 3 preceding and current row) as pv4, 
   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;

pv1: 分組內從起點到當前行的pv累積,如,11號的pv1=10號的pv+11號的pv, 12號=10號+11號+12號
pv2: 同pv1
pv3: 分組內(cookie1)所有的pv累加
pv4: 分組內當前行+往前3行,如,11號=10號+11號, 12號=10號+11號+12號, 13號=10號+11號+12號+13號, 14號=11號+12號+13號+14號
pv5: 分組內當前行+往前3行+往后1行,如,14號=11號+12號+13號+14號+15號=5+7+3+2+4=21
pv6: 分組內當前行+往后所有行,如,13號=13號+14號+15號+16號=3+2+4+4=13,14號=14號+15號+16號=2+4+4=10
復制代碼

NTILE,ROW_NUMBER,RANK,DENSE_RANK

NTILE(n)  用於將分組數據按照順序切分成n片,返回當前切片
NTILE不支持ROWS BETWEEN,比如 NTILE(2) OVER(PARTITION BY cookieid ORDER BY createtime ROWS BETWEEN 3 PRECEDING AND CURRENT ROW)
如果切片不均勻,默認增加第一個切片的分布

例子:

有下圖的1000家店鋪的價格數據。我們想知道,價格排名前30%的店鋪的平均價格,和后70%的。

 

思路:

把店鋪均勻的按價格遞減順序分成10片。然后取切片數=1,2,3的即為前30%。

sql:

復制代碼
-- 1 把記錄按價格順序拆分成10片
drop table if exists test_dp_price_rk;
create table test_dp_price_rk
as
select
 id,
 price,
 NTILE(10) OVER (order by price desc) as rn
from test_dp_price;

-- 2 按片取30%和70%,分別計算平均值
select
  new_rn,
  max(case when new_rn=1 then 'avg_price_first_30%' when new_rn=2 then 'avg_price_last_70%' end) as avg_price_name,
  avg(price) avg_price
from 
(
  select 
    id,
    price,
    rn,
    case when rn in (1,2,3) then 1 else 2 end as new_rn
  from test_dp_price_rk
)a
group by new_rn;
復制代碼

ROW_NUMBER()

ROW_NUMBER() –從1開始,按照順序,生成分組內記錄的序列
–比如,按照pv降序排列,生成分組內每天的pv名次
ROW_NUMBER() 的應用場景非常多,再比如,獲取分組內排序第一的記錄;獲取一個session中的第一條refer等。

select row_number() over (partition by cookieid order by piv desc) as rn from table;

—RANK() 生成數據項在分組中的排名,排名相等會在名次中留下空位    
—DENSE_RANK() 生成數據項在分組中的排名,排名相等會在名次中不會留下空位

select
  cookieid,
  createtime,
  pv,
  rank() over (partition by cookieid order by pv desc) as rn1,
  dense_rank() over (partition by cookieid order by pv desc) as rn2,
  row_number() over (partition by cookieid order by pv desc) as rn3
from cookie.cookie2 
where cookieid='cookie1';

row_number: 按順序編號,不留空位
rank: 按順序編號,相同的值編相同號,留空位
dense_rank: 按順序編號,相同的值編相同的號,不留空位

CUME_DIST :小於等於當前值的行數/分組內總行數
比如,統計小於等於當前薪水的人數,所占總人數的比例
select 
  dept,
  userid,
  sal,
  cume_dist() over (order by sal) as rn1,
  cume_dist() over (partition by dept order by sal) as rn2
from cookie.cookie3;

 

 –PERCENT_RANK :分組內當前行的RANK值-1/分組內總行數-1

 

  由於Hive 中的ORDER BY 對於大數據集 存在性能問題,

    延伸出了部分排序,以及將按相同KEY 控制到同一划分集合的需求。

    即以下兩個方案 SORT BY , DISTRIBUTE BY, 我們分別對這兩個方案進行介紹。

sort by

 SORT BY 是一個部分排序方案, 其只會在每個reducer 中對數據進行排序,

也就是執行一個局部排序過程。

使用sort by 你可以指定執行的reduce 個數 (set mapred.reduce.tasks=<number>),

 

對輸出的數據再執行歸並排序,即可以得到全部結果。

distribute by 

DISTRIBUTE BY 控制map 中的輸出在 reducer 中是如何進行划分的。

使用DISTRIBUTE BY 可以保證相同KEY的記錄被划分到一個Reduce 中。

cluster by    當sort by  和 distribute by  用到同一個字段 時 用  cluster by 代替







使用sort by 你可以指定執行的reduce 個數 (set mapred.reduce.tasks=<number>),

 

對輸出的數據再執行歸並排序,即可以得到全部結果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM