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?
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
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)
À 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 .
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.
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