2012-02-22 73 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