web-dev-qa-db-fra.com

Hive obtenant les n premiers enregistrements du groupe par requête

J'ai la table suivante dans la ruche

iD utilisateur, nom d'utilisateur, adresse d'utilisateur, clics, impressions, identifiant de page, nom de page

J'ai besoin de connaître les 5 meilleurs utilisateurs [identifiant, nom d'utilisateur, adresse d'utilisateur] en cliquant sur chaque page [identifiant de page, nom de page]

Je comprends que nous devons d’abord regrouper par [ID de page, nom de page] et au sein de chaque groupe, je souhaite passer commande par [clics, impressions], puis émettre seulement les 5 premiers utilisateurs adresse] pour chaque page mais je trouve difficile de construire la requête.

Comment pouvons-nous faire cela en utilisant Hive UDF?

22
TopCoder

Vous pouvez le faire avec une classe UDF () décrite ici: 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

Réponse révisée, corrigeant le bogue mentionné par @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

Notez que le UDAF rank () est appliqué à la colonne id-page, dont la nouvelle valeur est utilisée pour réinitialiser ou augmenter le compteur de rangs (par exemple un compteur réinitialisé pour chaque partition id-page)

15
Hai-Anh Trinh

À partir de Hive 0.11, vous pouvez le faire en utilisant la fonction intégrée de rank () de Hive et une sémantique plus simple en utilisant les fonctions intégrées d'analyse et de fenêtrage de Hive . Malheureusement, je n'ai pas trouvé autant d'exemples que je l'aurais souhaité, mais ils sont vraiment très utiles. En utilisant ceux-ci, à la fois rank () et WhereWithRankCond sont intégrés, de sorte que vous pouvez simplement faire:

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

Aucun fichier UDF requis et une seule sous-requête! En outre, toute la logique de rang est localisée.

Vous pouvez trouver d'autres exemples (bien que pas assez à mon goût) de ces fonctions dans cette Jira et sur le blog de ce type .

10
Eli

Vous pouvez utiliser each_top_k fonction of hivemall pour un calcul top-k efficace sur Apache Hive.

sélectionner
 identifiant de page, 
 identifiant d'utilisateur,
 clics 
 à partir de (
 sélectionner 
 each_top_k (5, id-page, clics, id-page, id-utilisateur) 
 comme (rang, clics, id-page, id-utilisateur) 
 à partir de (
 select 
 page-id, id-utilisateur, clique sur 
 depuis 
 mytable 
 DISTRIBUER PAR id-page TRIER PAR id-page 
) t1 
) t2 
 order by page-id ASC, clique sur DESC 

L'outil each_top_k UDTF est très rapide par rapport aux autres méthodes exécutant les requêtes top-k (par exemple, distributed by/rank) dans Hive car il ne contient pas le classement complet du résultat intermédiaire.

2
myui

Disons que vos données ressemblent à ceci:

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

La requête ci-dessous vous donnera: 

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

Résultat :

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

Ainsi, pour la page 1, vous obtenez 6 utilisateurs, car les utilisateurs avec le même nombre de clics sont classés de la même manière. 

Mais si vous recherchez exactement 5 utilisateurs, choisissez au hasard si plusieurs utilisateurs tombent au même rang. Vous pouvez utiliser la requête ci-dessous 

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

Résultat :

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