web-dev-qa-db-ja.com

クエリごとにグループ内の上位nレコードを取得するハイブ

Hiveには次の表があります

ユーザーID、ユーザー名、ユーザーアドレス、クリック、インプレッション、ページID、ページ名

各ページ[ページID、ページ名]をクリックして、上位5人のユーザー[ユーザーID、ユーザー名、ユーザーアドレス]を見つける必要があります。

最初に[page-id、page-name]でグループ化し、各グループ内で[clicks、impressions] descで並べ替えてから、上位5ユーザー[user-id、user-name、user-アドレス]を各ページに表示しますが、クエリを作成するのが難しいと感じています。

Hive UDFを使用してこれを行うにはどうすればよいですか?

22
TopCoder

ここで説明するrank()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
9
Maxime Brugidou

回答を修正し、@ 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

Rank()UDAFはページID列に適用され、その新しい値はランクカウンターのリセットまたは増加に使用されることに注意してください(たとえば、各ページIDパーティションのカウンターをリセット)

15
Hai-Anh Trinh

Hive 0.11の時点では、Hiveの組み込みrank()関数を使用してこれを行うことができ、 Hiveの組み込み分析およびウィンドウ関数 を使用してより単純なセマンティクスを使用できます。悲しいことに、私はこれらの例が私が望むほど多く見つけることができませんでしたが、それらは本当に本当に便利です。これらを使用して、rank()と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は不要で、サブクエリは1つだけです!また、ランクロジックはすべてローカライズされています。

これらの関数の例(私の好みでは十分ではありませんが)をもっと見つけることができます このJiraでこの男のブログ で。

11
Eli

each_top_k function of hivemall Apache Hiveでの効率的なtop-k計算のため。

 select 
 page-id、
 user-id、
 clicks 
 from(
 select 
 each_top_k( 5、ページID、クリック、ページID、ユーザーID)
 as(ランク、クリック、ページID、ユーザーID)
 from(
 select 
 page-id、user-id、clicks 
 from 
 mytable 
 DISTRIBUTE BY page-id SORT BY page-id 
)t1 
)t2 
ページID ASCで並べ替え、DESC 
をクリック

each_top_k UDTFは、top-kクエリを実行する他のメソッドと比較すると非常に高速です(例:distributed by/rank)Hiveでは、中間結果のランキング全体を保持しないためです。

2
myui

データが次のように見えるとしましょう:

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

そのため、同じクリック数のユーザーは同じランクであるため、page1のユーザーは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
1
greperror