Hive Explode / Lateral Просмотр нескольких массивов
У меня есть таблица кустов со следующей схемой:
COOKIE | PRODUCT_ID | CAT_ID | QTY
1234123 [1,2,3] [r,t,null] [2,1,null]
Как я могу нормализовать массивы, чтобы я получил следующий результат
COOKIE | PRODUCT_ID | CAT_ID | QTY
1234123 [1] [r] [2]
1234123 [2] [t] [1]
1234123 [3] null null
Я пробовал следующее:
select concat_ws('|',visid_high,visid_low) as cookie
,pid
,catid
,qty
from table
lateral view explode(productid) ptable as pid
lateral view explode(catalogId) ptable2 as catid
lateral view explode(qty) ptable3 as qty
однако результат получается как декартово произведение.
4 ответа
Вы можете использовать numeric_range
а также array_index
UDFs из Brickhouse ( http://github.com/klout/brickhouse), чтобы решить эту проблему. Существует информативное сообщение в блоге, подробно описывающее на http://brickhouseconfessions.wordpress.com/2013/03/07/exploding-multiple-arrays-at-the-same-time-with-numeric_range/
Используя эти UDF, запрос будет выглядеть примерно так:
select cookie,
array_index( product_id_arr, n ) as product_id,
array_index( catalog_id_arr, n ) as catalog_id,
array_index( qty_id_arr, n ) as qty
from table
lateral view numeric_range( size( product_id_arr )) n1 as n;
Я нашел очень хорошее решение этой проблемы без использования UDF, posexplode - очень хорошее решение:
ВЫБЕРИТЕ КУКИ, ePRODUCT_ID, eCAT_ID, eQTY ИЗ ТАБЛИЦЫ ПОСЛЕДОВАТЕЛЬНЫЙ ВЗГЛЯД позе xplode(PRODUCT_ID) ePRODUCT_IDAS seqp, ePRODUCT_ID LATERAL VIEW posexplode(CAT_ID) eCAT_ID AS seqc, eCAT_ID Боковой обзор posexplode(QTY) eQTY AS seqq, eDateReported ГДЕ seqp = seqc И seqc = seqq;
Вы можете сделать это с помощью posexplode, который предоставит целое число от 0 до n, чтобы указать позицию в массиве для каждого элемента в массиве. Затем используйте это целое число - назовите его pos (для позиции), чтобы получить совпадающие значения в других массивах, используя блочную нотацию, например:
select
cookie,
n.pos as position,
n.prd_id as product_id,
cat_id[pos] as catalog_id,
qty[pos] as qty
from table
lateral view posexplode(product_id_arr) n as pos, prd_id;
Это позволяет избежать использования импортированных UDF, а также объединения различных массивов (это имеет гораздо лучшую производительность).
Если вы используете Spark 2.4 в pyspark, используйте arrays_zip
с posexplode
:
df = (df
.withColumn('zipped', arrays_zip('col1', 'col2'))
.select('id', posexplode('zipped')))
Я пытался отработать ваш сценарий... попробуйте этот код -
create table info(cookie string,productid int,catid string,qty string);
insert into table info
select cookie,productid[myprod],categoryid[mycat],qty[myqty] from table
lateral view posexplode(productid) pro as myprod,pro
lateral view posexplode(categoryid) cate as mycat,cate
lateral view posexplode(qty) q as myqty,q
where myprod=mycat and mycat=myqty;
Примечание - в приведенных выше заявлениях, если вы разместите -select cookie,myprod,mycat,myqty from table
на месте select cookie,productid[myprod],categoryid[mycat],qty[myqty] from table
на выходе вы получите индекс элемента в массиве productid
, categoryid
а также qty
, Надеюсь, это будет полезно.