it-swarm.dev

Hive uzyskiwanie najlepszych rekordów w grupie według zapytania

Mam następującą tabelę w ulu

identyfikator użytkownika, nazwa użytkownika, adres użytkownika, kliknięcia, wyświetlenia, identyfikator strony, nazwa strony

Muszę znaleźć 5 największych użytkowników [identyfikator użytkownika, nazwa użytkownika, adres użytkownika] za pomocą kliknięć dla każdej strony [identyfikator strony, nazwa strony]

Rozumiem, że musimy najpierw pogrupować według [page-id, page-name] iw każdej grupie, którą chcę zamówić [dess, impressions] desc, a następnie emitować tylko 5 najlepszych użytkowników [user-id, user-user, user- adres] dla każdej strony, ale trudno mi skonstruować zapytanie.

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

22
TopCoder

Możesz to zrobić za pomocą UDF rang opisanego 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
9
Maxime Brugidou

Poprawiona odpowiedź, naprawianie błędu, o którym wspomina @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

Zauważ, że ranga () UDAF jest stosowana do kolumny id strony, której nowa wartość jest używana do resetowania lub zwiększania licznika rang (np. Reset licznika dla każdej partycji id strony)

15
Hai-Anh Trinh

Począwszy od Hive 0.11, możesz to zrobić za pomocą wbudowanej w Hive funkcji rank () i używając prostszej semantyki przy użyciu wbudowanych funkcji Hive Analytics i Windowing . Niestety, nie znalazłem tak wielu przykładów, jak bym chciał, ale są naprawdę, bardzo przydatne. Używając tych, zarówno rangowych (), jak i WhereWithRankCond, są wbudowane, więc możesz po prostu:

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

Nie wymaga UDF i tylko jedno podzapytanie! Również cała logika rang jest zlokalizowana.

Możesz znaleźć więcej (choć niewystarczających dla mnie) przykładów tych funkcji w blogu Jira i na tego faceta .

10
Eli

Możesz użyć funkcji each_top_k z hivemall dla wydajnego obliczenia top-k w Apache Hive.

Wybierz
 identyfikator strony, 
 identyfikator użytkownika,
 kliknięcia 
 z (
 wybierz 
 each_top_k (5, identyfikator strony, kliknięcia, identyfikator strony, identyfikator użytkownika) 
 as (pozycja, kliknięcia, identyfikator strony, identyfikator użytkownika) 
 z (
 wybierz 
 page-id, user-id, kliknięcia 
 z 
 mytable 
 DISTRIBUTE BY page-id SORT BY page-id 
) t1 
) t2 
 zamów według page-id ASC, kliknie DESC 

UDTF each_top_k jest bardzo szybki w porównaniu z innymi metodami uruchamiającymi kwerendy top-k (np. distributed by/rank) w gałęzi Hive, ponieważ nie zachowuje całego rankingu dla wyniku pośredniego.

2
myui

Powiedzmy, że Twoje dane wyglądają następująco:

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żej Query otrzymasz: 

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

Tak więc dla strony 1 otrzymujesz 6 użytkowników, ponieważ użytkownicy z taką samą liczbą kliknięć mają taką samą pozycję. 

Ale jeśli szukasz dokładnie 5 użytkowników i wybierzesz losowo, jeśli wielu użytkowników znajdzie się w tej samej randze. Możesz użyć poniższego zapytania 

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
1
greperror