Hiveには次の表があります
ユーザーID、ユーザー名、ユーザーアドレス、クリック、インプレッション、ページID、ページ名
各ページ[ページID、ページ名]をクリックして、上位5人のユーザー[ユーザーID、ユーザー名、ユーザーアドレス]を見つける必要があります。
最初に[page-id、page-name]でグループ化し、各グループ内で[clicks、impressions] descで並べ替えてから、上位5ユーザー[user-id、user-name、user-アドレス]を各ページに表示しますが、クエリを作成するのが難しいと感じています。
Hive UDFを使用してこれを行うにはどうすればよいですか?
ここで説明する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
回答を修正し、@ 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パーティションのカウンターをリセット)
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で と この男のブログ で。
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では、中間結果のランキング全体を保持しないためです。
データが次のように見えるとしましょう:
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