Je sais qu'il n'y a pas de moyen direct de transposer des données dans Hive. J'ai suivi cette question: Y at-il un moyen de transposer des données dans Hive? , mais comme il n’ya pas de réponse finale, ne peut pas aller jusqu'au bout.
Ceci est la table que j'ai:
| ID | Code | Proc1 | Proc2 |
| 1 | A | p | e |
| 2 | B | q | f |
| 3 | B | p | f |
| 3 | B | q | h |
| 3 | B | r | j |
| 3 | C | t | k |
Ici, Proc1 peut avoir un nombre quelconque de valeurs. ID, Code et Proc1 forment ensemble une clé unique pour cette table. Je souhaite pivoter/transposer cette table afin que chaque valeur unique de Proc1 devienne une nouvelle colonne et que la valeur correspondante de Proc2 soit la valeur de cette colonne pour la ligne correspondante. Pour résumer, j'essaie d'obtenir quelque chose comme:
| ID | Code | p | q | r | t |
| 1 | A | e | | | |
| 2 | B | | f | | |
| 3 | B | f | h | j | |
| 3 | C | | | | k |
Dans la nouvelle table transformée, l'ID et le code sont la seule clé primaire. D'après le billet que j'ai mentionné ci-dessus, je pourrais aller aussi loin en utilisant toDAmap UDAF. (Avertissement - ceci peut ne pas être un pas dans la bonne direction, mais juste mentionner ici, si c'est)
| ID | Code | Map_Aggregation |
| 1 | A | {p:e} |
| 2 | B | {q:f} |
| 3 | B | {p:f, q:h, r:j } |
| 3 | C | {t:k} |
Mais je ne sais pas comment aller de cette étape au tableau pivot/transposé que je veux . Toute aide sur la façon de procéder sera géniale! Merci.
Voici la solution que j'ai finalement utilisée:
add jar brickhouse-0.7.0-SNAPSHOT.jar;
CREATE TEMPORARY FUNCTION collect AS 'brickhouse.udf.collect.CollectUDAF';
select
id,
code,
group_map['p'] as p,
group_map['q'] as q,
group_map['r'] as r,
group_map['t'] as t
from ( select
id, code,
collect(proc1,proc2) as group_map
from test_sample
group by id, code
) gm;
Le fichier UDF to_map a été utilisé à partir du référentiel brickhouse: https://github.com/klout/brickhouse
Voici l'approche que j'ai utilisée pour résoudre ce problème en utilisant la fonction UDF interne de Hive, "map":
select
b.id,
b.code,
concat_ws('',b.p) as p,
concat_ws('',b.q) as q,
concat_ws('',b.r) as r,
concat_ws('',b.t) as t
from
(
select id, code,
collect_list(a.group_map['p']) as p,
collect_list(a.group_map['q']) as q,
collect_list(a.group_map['r']) as r,
collect_list(a.group_map['t']) as t
from (
select
id,
code,
map(proc1,proc2) as group_map
from
test_sample
) a
group by
a.id,
a.code
) b;
"concat_ws" et "map" sont Hive udf et "collect_list" est un Hive udaf.
Encore une autre solution.
Pivot en utilisant Hivemallto_map
.
SELECT
uid,
kv['c1'] AS c1,
kv['c2'] AS c2,
kv['c3'] AS c3
FROM (
SELECT uid, to_map(key, value) kv
FROM vtable
GROUP BY uid
) t
uid c1 c2 c3
101 11 12 13
102 21 22 23
Unpivot
SELECT t1.uid, t2.key, t2.value
FROM htable t1
LATERAL VIEW explode (map(
'c1', c1,
'c2', c2,
'c3', c3
)) t2 as key, value
uid key value
101 c1 11
101 c2 12
101 c3 13
102 c1 21
102 c2 22
102 c3 23
Je n'ai pas écrit ce code, mais je pense que vous pouvez utiliser certaines des fonctions définies par l'utilisateur fournies par klouts brickhouse: https://github.com/klout/brickhouse
Spécifiquement, vous pouvez faire quelque chose comme utiliser leur collection comme mentionné ici: http://brickhouseconfessions.wordpress.com/2013/03/05/use-collect-to-avoid-the-self-join/
et ensuite exploser les tableaux (ils seront de longueur différente) en utilisant les méthodes détaillées dans ce post http://brickhouseconfessions.wordpress.com/2013/03/07/exploding-multiple-arrays-at-the-same- time-with-numeric_ra
Vous pouvez utiliser les déclarations de cas et l'aide de collect_set pour y parvenir. Vous pouvez vérifier cela. Vous pouvez vérifier la réponse détaillée sur - http://www.analyticshut.com/big-data/Hive/pivot-rows-to-columns-in-Hive/
Voici la requête pour référence,
SELECT resource_id,
CASE WHEN COLLECT_SET(quarter_1)[0] IS NULL THEN 0 ELSE COLLECT_SET(quarter_1)[0] END AS quarter_1_spends,
CASE WHEN COLLECT_SET(quarter_2)[0] IS NULL THEN 0 ELSE COLLECT_SET(quarter_2)[0] END AS quarter_2_spends,
CASE WHEN COLLECT_SET(quarter_3)[0] IS NULL THEN 0 ELSE COLLECT_SET(quarter_3)[0] END AS quarter_3_spends,
CASE WHEN COLLECT_SET(quarter_4)[0] IS NULL THEN 0 ELSE COLLECT_SET(quarter_4)[0] END AS quarter_4_spends
FROM (
SELECT resource_id,
CASE WHEN quarter='Q1' THEN amount END AS quarter_1,
CASE WHEN quarter='Q2' THEN amount END AS quarter_2,
CASE WHEN quarter='Q3' THEN amount END AS quarter_3,
CASE WHEN quarter='Q4' THEN amount END AS quarter_4
FROM billing_info)tbl1
GROUP BY resource_id;
Ci-dessous est aussi un moyen pour Pivot
SELECT TM1_Code, Product, Size, State_code, Description
, Promo_date
, Price
FROM (
SELECT TM1_Code, Product, Size, State_code, Description
, MAP('FY2018Jan', FY2018Jan, 'FY2018Feb', FY2018Feb, 'FY2018Mar', FY2018Mar, 'FY2018Apr', FY2018Apr
,'FY2018May', FY2018May, 'FY2018Jun', FY2018Jun, 'FY2018Jul', FY2018Jul, 'FY2018Aug', FY2018Aug
,'FY2018Sep', FY2018Sep, 'FY2018Oct', FY2018Oct, 'FY2018Nov', FY2018Nov, 'FY2018Dec', FY2018Dec) AS tmp_column
FROM CS_ME_Spirits_30012018) TmpTbl
LATERAL VIEW EXPLODE(tmp_column) exptbl AS Promo_date, Price;
Pour Unpivot, nous pouvons simplement utiliser la logique ci-dessous.
SELECT Cost.Code, Cost.Product, Cost.Size
, Cost.State_code, Cost.Promo_date, Cost.Cost, Sales.Price
FROM
(Select Code, Product, Size, State_code, Promo_date, Price as Cost
FROM Product
Where Description = 'Cost') Cost
JOIN
(Select Code, Product, Size, State_code, Promo_date, Price as Price
FROM Product
Where Description = 'Sales') Sales
on (Cost.Code = Sales.Code
and Cost.Promo_date = Sales.Promo_date);
En cas de valeur numérique, vous pouvez utiliser la requête Hive ci-dessous:
Échantillon de données
ID cust_freq Var1 Var2 frequency
220444 1 16443 87128 72.10140547
312554 6 984 7339 0.342452643
220444 3 6201 87128 9.258396518
220444 6 47779 87128 2.831972441
312554 1 6055 7339 82.15209213
312554 3 12868 7339 4.478333954
220444 2 6705 87128 15.80822558
312554 2 37432 7339 13.02712127
select id, sum(a.group_map[1]) as One, sum(a.group_map[2]) as Two, sum(a.group_map[3]) as Three, sum(a.group_map[6]) as Six from
( select id,
map(cust_freq,frequency) as group_map
from table
) a group by a.id having id in
( '220444',
'312554');
ID one two three six
220444 72.10140547 15.80822558 9.258396518 2.831972441
312554 82.15209213 13.02712127 4.478333954 0.342452643
In above example I have't used any custom udf. It is only using in-built Hive functions.
Note :For string value in key write the vale as sum(a.group_map['1']) as One.