2012-02-22 10 views
22

ho seguente tabella in alveareHive ottenendo n record nel Gruppo dal interrogazione

user-id, nome utente, utente-indirizzo, clic, impressioni, pagina-id, pagina-nome

I bisogno di scoprire i primi 5 utenti [id-utente, nome-utente, indirizzo-utente] per click per ogni pagina [id-pagina, nome-pagina]

Capisco che dobbiamo prima raggruppare per [pagina- id, nome-pagina] e all'interno di ogni gruppo che voglio ordinare [clic, impressioni] desc e quindi emettere solo i primi 5 utenti [user-id, user-name, user-address] per ogni pagina ma trovo difficile costruire la query.

Come possiamo farlo utilizzando HIve UDF?

risposta

9

È possibile farlo con un rango() UDF descritto qui: 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

Ciao Maxime, Ci scusiamo per ti dà fastidio come questo. Sto anche avendo il problema simile. Ho postato su SO, ma non ho avuto una buona risposta dato che sto lavorando con Hive e HiveQL è nuovo per me. [http://stackoverflow.com/questions/11405446/find-10-latest-record-for-each-buyer-id-for-yesterdays-date](http://stackoverflow.com/questions/11405446/find- 10-ultima-record per-ogni-acquirente-id-per-ieri-oggi). Sarà di grande aiuto per me. – ferhan

+9

Ho solo messo in ore facendo questo lavoro ma non ha funzionato. Il bug è che ti stai prima classificando e poi facendo DISTRIBUIRE BY e SORT BY. Invece dovresti applicare il rank in una query esterna e usare DISTRIBUTE BY e SORT BY in una query interna. Ad esempio, selezionare ID pagina, ID utente, clic FROM (ID pagina SELECT, ID utente, rank (ID utente) come ranking, clic FROM (SELECT * FROM mytable DISTRIBUTE BY ID-id, user-id SORT PER ID-id, id-utente, clicca DESC) a) b WHERE rank <5 ORDER BY id-page, rank; –

+2

Confermato che @HimanshuGahlot è corretto. La risposta ha un * BUG *! Devi usare rank() in una query esterna e usare DISTRIBUTE/SORT BY nella query interna! –

15

risposta riveduta, che fissa il bug come detto da @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 

Si noti che il rango() UDAF viene applicato alla colonna id-pagina, il cui nuovo valore viene utilizzato per reimpostare o aumentare il contatore di rango (es. Contatore di reset per ogni partizione id di pagina)

+0

Cool .. Ha salvato la mia ricerca :) – minhas23

9

Come da Hive 0.11, è possibile farlo s usando la funzione built in rank() di Hive e usando semantica più semplice usando Hive's built-in Analytics and Windowing functions. Purtroppo non ho potuto trovare tanti esempi con questi come avrei voluto, ma sono davvero, davvero utili. Utilizzando questi, sia rango() e WhereWithRankCond sono costruiti in, in modo da poter fare solo:

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 richiesto, e solo una subquery! Inoltre, tutta la logica di classificazione è localizzata.

È possibile trovare alcuni esempi (anche se non sufficienti per i miei gusti) di queste funzioni in this Jira e su this guy's blog.

2

È possibile utilizzare each_top_k function di hivemall per un'efficiente computazione top-k su 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 

Il each_top_k UDTF è molto veloce rispetto ad altri metodi di esecuzione query top-k (ad esempio, distributed by/rank) in alveare perché non tiene tutta classifica per il risultato intermedio.

1

Diciamo i dati si presenta come segue:

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 

seguito Query vi darà:

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 

Risultato:

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 

Così, per page1 si stanno ottenendo 6 utenti, dato che gli utenti con lo stesso numero di clic sono classificati uguali.

Ma, se stai cercando esattamente 5 utenti, e scegli casualmente nel caso in cui più utenti cadano nello stesso rango.È possibile utilizzare la query di seguito

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 

Risultato:

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 
Problemi correlati