Вот решение. Это немного похоже на взлом, но он будет работать независимо от количества ключей, которые у вас есть.
udf0.py
#/usr/bin/python
import sys
from collections import Counter
for line in sys.stdin:
words = line.strip().split('\t')
c = Counter()
for word in words:
d = {}
s = word.split(',')
for ss in s:
k,v = ss.split(':')
d[k] = int(v)
c.update(d)
print ','.join([str(k)+':'+str(v) for k,v in dict(c).iteritems()])
udf1.py
#!/usr/bin/python
import sys
for line in sys.stdin:
w0, w1 = line.strip().split('\t')
out = {}
d = {}
l = []
s0 = w0.strip().split(',')
s1 = w1.strip().split(',')
for ss in s0:
k,v = ss.split(':')
d[k] = int(v)
for ss in s1:
l.append(ss)
for keys in l:
if d.get(keys, None) is not None:
out[keys] = d[keys]
else:
out[keys] = 0
print ','.join([str(k)+':'+str(v) for k,v in out.iteritems()])
Запрос улья:
add file /home/username/udf0.py;
add file /home/username/udf1.py;
SELECT TRANSFORM(dict, unique_keys)
USING 'python udf1.py'
AS (final_map STRING)
FROM (
SELECT DISTINCT dict
, CONCAT_WS(',', unique_keys) as unique_keys
FROM (
SELECT dict
, COLLECT_SET(keys) OVER () AS unique_keys
FROM (
SELECT dict
, keys
FROM (
SELECT dict
, map_keys(str_to_map(dict)) AS key_arr
FROM (
SELECT TRANSFORM (col1, col2)
USING 'python udf0.py'
AS (dict STRING)
FROM db.tbl ) x ) z
LATERAL VIEW EXPLODE(key_arr) exptbl AS keys ) a ) b ) c
Вывод:
a:6,b:2,c:6,d:0
a:21,b:7,c:0,d:5
Объяснение:
Первый UDF возьмет вашу строку, преобразует ее в словарь Python и обновит ключи (т.е. сложит значения с совпадающими ключами вместе). Поскольку вы не знаете фактических ключей, вы будете знать, что необходимо извлечь ключи из каждого словаря (map_keys()
в запросе улья), взорвать таблицу, а затем собрать их обратно в уникальный набор. Теперь у вас есть все возможные ключи в любом словаре. Затем оттуда вы можете использовать вторую UDF для импорта словаря, созданного в первой UDF, проверить, присутствует ли каждый ключ, а если нет, поставить ноль для его значения.
person
gobrewers14
schedule
25.08.2016