2012-02-22 4 views
22

He siguiente tabla en la colmenaColmena conseguir los mejores registros n en el grupo de consulta

identificación del usuario, del nombre de usuario, fácil de dirección, clics, impresiones, página-id, página nombre

I necesita encontrar los 5 mejores usuarios [ID de usuario, nombre de usuario, dirección de usuario] haciendo clic para cada página [page-id, page-name]

Entiendo que necesitamos agrupar primero por [page- id, page-name] y dentro de cada grupo quiero ordenar por [clicks, impresiones] desc y luego emitir solo los primeros 5 usuarios [user-id, user-name, user-address] para cada página pero me resulta difícil construir la consulta.

¿Cómo podemos hacer esto usando HIVE UDF?

Respuesta

9

Puede hacerlo con un rango() UDF describe aquí: 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

Hola Maxime, Lo siento por molestar te gusta esto. También estoy teniendo el problema similar. Publiqué en el SO, pero no obtuve una buena respuesta porque estoy trabajando con Hive y HiveQL es nuevo para mí. [http://stackoverflow.com/questions/11405446/find-10-latest-record-for-each-buyer-id-for-yesterdays-date](http://stackoverflow.com/questions/11405446/find- 10-latest-record-for-each-buyer-id-for-yesterdays-date). Será de gran ayuda para mí. – ferhan

+9

Acabo de poner horas en hacer este trabajo, pero no funcionó. El error es que primero estás clasificando y luego haciendo DISTRIBUIR BY y SORT BY. En su lugar, debe aplicar rango en una consulta externa y usar DISTRIBUIR BY y SORT BY en una consulta interna. Por ejemplo, SELECCIONAR identificador de página, ID de usuario, clics DESDE (SELECCIONAR ID de página, ID de usuario, rango (ID de usuario) como rango, clics DESDE (SELECCIONAR * FROM mytable DISTRIBUIR POR ID de página, ID de usuario CLASIFICAR POR ID de página, ID de usuario, hace clic en DESC) a) b DONDE rango <5 ORDER BY page-id, rank; –

+2

Confirmó que @HimanshuGahlot es correcto. ¡La respuesta tiene un * ERROR *! Debe usar rank() en una consulta externa y usar DISTRIBUTE/SORT BY en la consulta interna. –

15

respuesta revisada, corregir los fallos según lo mencionado por @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 

Tenga en cuenta que el rango() UDAF se aplica a la columna page-id, cuyo nuevo valor se usa para restablecer o aumentar el contador de rango (por ejemplo, reiniciar el contador para cada partición de ID de página)

+0

Genial ... Se guardó mi búsqueda :) – minhas23

9

A partir de Hive 0.11, puede hacer esto s utilizando la función incorporada de rango() de Hive y utilizando una semántica más simple usando Hive's built-in Analytics and Windowing functions. Lamentablemente, no pude encontrar tantos ejemplos con estos como me hubiera gustado, pero son realmente útiles. El uso de estos, tanto rango() y WhereWithRankCond están integradas, por lo que sólo pueden hacer:

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 se requiere UDF, y sólo una sub consulta! Además, toda la lógica de rango está localizada.

Puede encontrar algunos ejemplos más (aunque no suficientes para mi gusto) de estas funciones in this Jira y en this guy's blog.

2

Puede usar each_top_k function de hivemall para un cálculo de top-k eficiente en 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 

El UDTF each_top_k es muy rápido en comparación con otros métodos que se ejecutan consultas top-k (por ejemplo, distributed by/rank) en la colmena porque no se mantiene toda la clasificación para el resultado intermedio.

1

Digamos que sus datos se parece a lo siguiente:

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 

continuación de consulta le 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 

Resultado:

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 

Así, por page1 que está recibiendo 6 usuarios, ya que los usuarios con el mismo número de clics se clasifican igual.

Pero, si busca exactamente 5 usuarios, y elija al azar en caso de que varios usuarios caigan en el mismo rango.Puede utilizar la siguiente consulta

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 

Resultado:

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 
Cuestiones relacionadas