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, Надеюсь, это будет полезно.

Другие вопросы по тегам