2012-02-22 2 views
22

я следующую таблицу в улейHive получать верхние п записей в группе по запросу

идентификатор пользователя, имя пользователя, пользователь-адрес, клики, показы, стр-ид, страница имен

I вам нужно найти 5 лучших пользователей [user-id, user-name, user-address] по щелчкам для каждой страницы [page-id, page-name]

Я понимаю, что нам нужно сначала сгруппировать [page- id, page-name] и внутри каждой группы я хочу упорядочить [клики, показы] desc, а затем испустить только 5 лучших пользователей [user-id, user-name, user-address] для каждой страницы, но мне трудно постройте запрос.

Как мы можем это сделать, используя 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

Привет Maxime, Извините, что беспокою вас, как это. У меня также есть аналогичная проблема. Я опубликовал на 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

+9

Я просто потратил часы на выполнение этой работы, но это не сработало. Ошибка в том, что вы первый рейтинг, а затем выполняете DISTRIBUTE BY и SORT BY. Вместо этого вы должны применять ранжирование во внешнем запросе и использовать DISTRIBUTE BY и SORT BY во внутреннем запросе. Например, идентификатор страницы SELECT, идентификатор пользователя, клики FROM (идентификатор страницы SELECT, идентификатор пользователя, ранг (идентификатор пользователя) в качестве ранга, клики FROM (SELECT * FROM mytable DISTRIBUTE BY page-id, user-id SORT BY page-id, идентификатор пользователя, клики DESC) a) b WHERE rank <5 ORDER BY page-id, rank; –

+2

Подтверждено, что @HimanshuGahlot является правильным. Ответ имеет * BUG *! Вы должны использовать rank() во внешнем запросе и использовать DISTRIBUTE/SORT BY во внутреннем запросе! –

15

пересмотренную ответ, фиксируя ошибку, как было упомянуто @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 применяется к столбцу идентификатора страницы, новое значение которого используется для сброса или увеличения счетчика ранга (например, счетчик сброса для каждого раздела с идентификатором страницы)

+0

Прохладный .. Он спас мой поиск :) – minhas23

9

Как и в случае с улей 0.11, вы можете сделать это используя функцию 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 Jira и на this guy's blog.

2

Вы можете использовать each_top_k function из hivemall для эффективного вычисления top-k в Apache Hive.

 
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 

each_top_k UDTF очень быстро по сравнению с другими методами, работающих под управлением топ-K запросов (например, distributed by/rank) в улей, потому что он не держит весь рейтинг для промежуточного результата.

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 

Ниже Query даст вам:

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 
Смежные вопросы