2012-02-22 12 views
22

Mam poniższej tabeli w chrząszczaHive uzyskanie najwyższej rekordy nw grupy przez zapytania

user-ID, User-Name, łatwość adresowej, kliknięcia, wyświetlenia, strona-id, strona-name

I musisz znaleźć 5 najlepszych użytkowników [identyfikator użytkownika, nazwę użytkownika, adres użytkownika] przez kliknięcia dla każdej strony [id-strony, nazwa-strony]

Rozumiem, że musimy najpierw pogrupować według [page- id, nazwa-strony] iw ramach każdej grupy chcę zamówić przez [kliknięcia, wyświetlenia], a następnie wyemitować tylko 5 najlepszych użytkowników [identyfikator użytkownika, nazwę użytkownika, adres użytkownika] dla każdej strony, ale napotykam na trudności skonstruuj zapytanie.

Jak możemy to zrobić za pomocą HIVE UDF?

Odpowiedz

9

Można zrobić to z rankingu() UDF opisane tutaj: 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

Hi Maxime, przepraszam za przeszkadza Ci tak. Mam podobny problem. Napisałem na SO, ale nie mam żadnej dobrej odpowiedzi, ponieważ pracuję z Hive i HiveQL jest dla mnie nowy. [http://stackoverflow.com/questions/11405446/find-10-latest-record-for-each-buyer-id-for-yesterdays-date](http://stackoverflow.com/questions/11405446/find- 10 ostatnich rekordów dla każdego kupującego, id-in-yesterdays-date). To mi bardzo pomoże. – ferhan

+9

Po prostu poświęciłem godziny na wykonanie tej pracy, ale to nie zadziałało. Błąd polega na tym, że najpierw dokonujesz rankingu, a następnie wykonujesz DISTRIBUTE BY i SORT BY BY. Zamiast tego powinieneś zastosować rangę w zewnętrznej kwerendzie i użyć DISTRIBUTE BY i SORT BY BY w wewnętrznej kwerendzie. Na przykład SELECT id-strony, user-id, kliknięcia FROM (SELECT id-strony, user-id, ranga (user-id) jako rang, kliknie FROM (SELECT * FROM mytable DISTRIBUTE BY id-strony, user-id SORT BY id-strony, id-użytkownika, klika DESC) a) b WHERE pozycja <5 ORDER BY id-page, ranga; –

+2

Potwierdzono, że @HimanshuGahlot jest poprawny. Odpowiedź ma * BUG *! Musisz użyć rank() w zewnętrznej kwerendzie i użyj DISTRIBUTE/SORT BY w wewnętrznej kwerendzie! –

15

uaktualnienia odpowiedź, poprawiania błędów, jak wspomniano przez @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 

Należy zauważyć, że stopień() UDAF jest stosowane do kolumny id strony, której nowa wartość służy do resetowania lub zwiększania licznika rang (np. Resetuj licznik dla każdej partycji id-strony)

+0

Fajnie .. Zapisałem moje wyszukiwanie :) – minhas23

9

Od Ula 0.11, możesz zrobić s używając wbudowanej funkcji Hive w rank() i używając prostszej semantyki używając Hive's built-in Analytics and Windowing functions. Niestety, nie mogłem znaleźć tak wielu przykładów, jak bym chciał, ale są one naprawdę przydatne. Korzystanie z nich, zarówno rangi() i WhereWithRankCond są wbudowane, więc można po prostu zrobić: wymagana

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 

No UDF, a tylko jeden Podzapytanie! Ponadto cała logika rang jest zlokalizowana.

Możesz znaleźć więcej (choć niewystarczająco jak na mój gust) przykładów tych funkcji in this Jira i this guy's blog.

2

Możesz użyć each_top_k function z hivemall, aby uzyskać wydajne obliczenia na najwyższym poziomie w 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 jest bardzo szybki w porównaniu do innych metod prowadzących zapytania top-K (np distributed by/rank) w Ulu, ponieważ nie trzymać cały ranking wyniku pośredniego.

1

Powiedzmy dane wygląda jak następuje:

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 

poniższe zapytanie daje:

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 

Wynik:

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 

Więc dla Strona1 otrzymujesz 6 użytkowników, ponieważ użytkownicy z taką samą liczbą kliknięć są na tym samym poziomie.

Ale jeśli szukasz dokładnie 5 użytkowników i wybierzesz losowo, w przypadku, gdy wielu użytkowników przypada na tę samą pozycję.Można użyć poniższe zapytanie

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 

Wynik:

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