2012-02-22 41 views
22

我有以下的蜂巢蜂巢获得A组前N个记录被查询

用户ID,用户名,用户地址,点击次数,展示次数,页面ID,页面名称

我表需要找出前5名用户[用户ID,用户名,用户地址]按点击每一页[第-ID,页面名称]

我明白,我们需要先将由[PAGE- id,page-name]以及我希望通过[点击次数,展示次数] desc排序的每个组内,然后每个页面仅发布前5位用户[用户名,用户名,用户地址],但我发现很难构建查询。

我们如何使用HIVE UDF来做到这一点?

回答

9

您可以用等级做()UDF描述这里:http://ragrawal.wordpress.com/2011/11/18/extract-top-n-records-in-each-group-in-hadoophive/

SELECT page-id, user-id, clicks 
FROM (
    SELECT page-id, user-id, rank(user-id) as rank, clicks 
    FROM mytable 
    DISTRIBUTE BY page-id, user-id 
    SORT BY page-id, user-id, clicks desc 
) a 
WHERE rank < 5 
ORDER BY page-id, rank 
+0

嗨马克西姆,对不起打扰你这样。我也有类似的问题。我已经发布了SO,但没有得到任何好的反应,因为我正在与Hive一起工作,而HiveQL对我来说是新的。 [http://stackoverflow.com/questions/11405446/find-10-latest-record-for-each-buyer-id-for-yesterdays-date](http://stackoverflow.com/questions/11405446/find- 10 - 最新记录换每个买方-ID换昨日最新)。这对我很有帮助。 – ferhan 2012-07-10 22:18:11

+9

我只是放了几个小时做这项工作,但它没有奏效。错误在于你先排名然后再做DISTRIBUTE BY和SORT BY。相反,您应该在外部查询中应用排名,并在内部查询中使用DISTRIBUTE BY和SORT BY。例如,SELECT page-id,user-id,点击FROM(SELECT page-id,user-id,rank(user-id)as rank,点击FROM(SELECT * FROM mytable DISTRIBUTE BY page-id,user-id SORT BY page-id,user-id,点击DESC)a)b WHERE rank <5 ORDER BY page-id,rank; – 2013-03-19 21:30:53

+2

确认@HimanshuGahlot是正确的。答案有* BUG *!您必须在外部查询中使用rank(),并在内部查询中使用DISTRIBUTE/SORT BY! – 2013-04-04 07:43:27

15

修订的答案,修复bug由@Himanshu Gahlot

SELECT page-id, user-id, clicks 
FROM (
    SELECT page-id, user-id, rank(page-id) as rank, clicks FROM (
     SELECT page-id, user-id, clicks FROM mytable 
     DISTRIBUTE BY page-id 
     SORT BY page-id, clicks desc 
) a) b 
WHERE rank < 5 
ORDER BY page-id, rank 

注意提到,秩() UDAF应用于page-id列,其新值用于重置或增加等级计数器(例如每个页面分区的重置计数器)

+0

酷..它保存了我的搜索:) – minhas23 2016-01-11 19:48:29

9

从Hive 0.11开始,您可以通过s使用Hive内置的rank()函数并使用更简单的语义使用Hive's built-in Analytics and Windowing functions。可悲的是,我找不到像我喜欢的那样多的例子,但它们确实非常有用。使用这些,均居()和WhereWithRankCond是建立在,所以你可以这样做:需要

SELECT page-id, user-id, clicks 
FROM (
    SELECT page-id, user-id, rank() 
      over (PARTITION BY page-id ORDER BY clicks DESC) as rank, clicks 
    FROM my table 
) ranked_mytable 
WHERE ranked_mytable.rank < 5 
ORDER BY page-id, rank 

没有UDF,只有一个子查询!此外,所有的排名逻辑都是本地化的。

您可以在这些功能in this Jirathis guy's blog上找到更多(尽管不够我喜欢)的功能。

2

您可以使用each_top_k functionhivemall在Apache Hive上进行高效的top-k计算。

 
select 
    page-id, 
    user-id, 
    clicks 
from (
    select 
    each_top_k(5, page-id, clicks, page-id, user-id) 
     as (rank, clicks, page-id, user-id) 
    from (
    select 
     page-id, user-id, clicks 
    from 
     mytable 
    DISTRIBUTE BY page-id SORT BY page-id 
) t1 
) t2 
order by page-id ASC, clicks DESC 

相比运行在蜂房的top-k查询(例如,distributed by/rank)的其他方法时,因为它不保持中间结果整个排名的each_top_k UDTF是非常快的。

1

让我们假设你的数据看起来像以下:

page-id user-id clicks 
page1  user1  10 
page1  user2  10 
page1  user3  9 
page1  user4  8 
page1  user5  7 
page1  user6  7 
page1  user7  6 
page1  user8  5 
page2  user1  20 
page2  user2  19 
page2  user3  18 

下面的查询会给你:

SELECT page-id, user-id, clicks, rank 
FROM (
    SELECT page-id, user-id, rank() 
      over (PARTITION BY page-id ORDER BY clicks DESC) as rank, clicks 
    FROM your_table 
) ranked_table 
WHERE ranked_table.rank <= 5 

结果:

page-id user-id clicks rank 
page1  user1  10  1 
page1  user2  10  1 
page1  user3  9  3 
page1  user4  8  4 
page1  user5  7  5 
page1  user6  7  5 
page2  user1  20  1 
page2  user2  19  2 
page2  user3  18  3 

因此,对于第1页你得到6用户,因为点击次数相同的用户排名相同。

但是,如果您正在寻找5个用户,并且随机选择多个用户属于同一个等级。您可以使用下面的查询

SELECT page-id, user-id, clicks, rank 
FROM (
    SELECT page-id, user-id, row_number() 
      over (PARTITION BY page-id ORDER BY clicks DESC) as rank, clicks 
    FROM your_table 
) ranked_table 
WHERE ranked_table.rank <= 5 

结果:

page-id user-id clicks rank 
page1  user1  10  1 
page1  user2  10  2 
page1  user3  9  3 
page1  user4  8  4 
page1  user5  7  5 
page2  user1  20  1 
page2  user2  19  2 
page2  user3  18  3