row_number()在hive中是一个函数,必须带一个或者多个列参数,如row_number(col1, ....),它的作用是按指定的列进行分组生成行序列,在row_number(a,b) 时,若两条记录的a,b列相同,则行序列+1,否则重新计数。
因为hive是基于mapreaduce的,必须保证row_number执行是在reduce中,并且row_number中使用的列中,列值相同的记录要再同一个reduce中,否则row_number的行为是无意义的。
实例:
目前有一个表app_product_da,需要求出user_log_acct,item_sku_id维度下最近生成的一条数据。
实现如下:
方式一:
select
t2.user_log_acct
,t2.item_sku_id
,t2.time
from
(select *
from
(select * from app.app_product_da where dt = 'yesterday') t1
distribute by item_sku_id
sort by user_log_acct,item_sku_id,time desc
) t2
where row_number(t2.user_log_acct, t2.item_sku_id) = 1
;
方式二:
--由于item_sku_id数据量比较大,distribute by item_sku_id 生成的reduce数量比较多,性能比较低;可以修改如下,100可以根据不同情况来调:
select
t2.user_log_acct
,t2.item_sku_id
,t2.time
from
(select *
from
(select * from app.app_product_da where dt = 'yesterday') t1
distribute by pmod(item_sku_id, 100)
sort by user_log_acct,item_sku_id,time desc
) t2
where row_number(t2.user_log_acct, t2.item_sku_id) = 1
;
方式三:
--由于有可能有些hive版本不知道上面两种直接where后面row_number(t2.user_log_acct, t2.item_sku_id) = 1
select
t3.user_log_acct
,t3.item_sku_id
,t3.time
from
(select
t2.user_log_acct
,t2.item_sku_id
,t2.time
,row_number(t2.user_log_acct, t2.item_sku_id) r_num
from
(select *
from
(select * from app.app_product_da where dt = 'yesterday') t1
distribute by pmod(item_sku_id, 100)
sort by user_log_acct,item_sku_id,time desc
) t2
) t3
where t3.r_num = 1
;
注意点:
1.使用子查询保证row_number在reduce端执行。
2.使用distribute by item_sku_id sort by user_log_acct,item_sku_id,time desc来保证item_sku_id相同的记录被分配到相同的reduce中。