2017-07-14 15 views
1

文字列の1つにXMLが含まれているHiveテーブルがあります。Xpathを使用してXMLノードをHiveテーブルに抽出する

DataTable 
key: string 
xml: string 

およびXML形式であること:0..Nエンティティノードと

<xml> 
    <entity> 
     <property type="alpha">123</property> 
     <property type="beta">abc</property> 
     <property type="delta">...</property> 
    </entity> 
    <entity> 
     <property type="alpha">321</property> 
     <property type="beta">cba</property> 
     <property type="delta">---</property> 
    </entity> 
</xml> 

簡略化するために、テーブルがあると仮定する。

私は、次の形式で新しいハイブのテーブルにこのデータを変換したい:

TransformedTable 
key: string 
alpha: string 
beta: string 
delta: string 

が、私は難しいそれを見つけることです。私はハイヴェにはかなり新しいですが、このような何かを考えていれば、それは道のりです。

次の質問は関連しています

が、答えを持っていません。そして、この質問は、関連する答えがあります。

を私は、私はこのケースでのxml SerDeを使用することができるとは思いません。その研究を通して、私はこのようなものを試してみた:

select key, 
     xpath(xml, 'xml/entity/property[@type="alpha"]/text()')) as alpha, 
     xpath(xml, 'xml/entity/property[@type="beta"]/text()')) as beta, 
     xpath(xml, 'xml/entity/property[@type="delta"]/text()')) as delta 
    from DataTable 

それは、この中で結果:

代わりに私が本当に欲しいものの
key1 ["123", "321"] ["abc", "cba"] ["...", "---"] 
key2 ["123", "321"] ["abc", "cba"] ["...", "---"] 

key1 123 abc ... 
key1 321 cba --- 
key2 123 abc ... 
key2 321 cba --- 

ありがとうこれを読む時間を割いて、あなたが私に与えることができるアイデアを感謝します!

答えて

0

配列ベースのデータは、LATERAL VIEWexplodeなどのテーブル生成関数との組み合わせでリレーションに「結合」することができます。この場合のさらなる複雑化は、alphabetaおよびdeltaの配列に対応するLATERAL VIEWの3つの別個の出現を必要とするため、結果セットに完全なデカルト生成物のリスクが生じる。すべてのアルファ/ベータ/デルタパーミュテーションは別々の行を生成します。

デカルト積を避けるには、posexplodeという関数の変形を使用できます。この関数は、元の配列の数値インデックスとデータ値の両方を生成します。次に、フィルタリング条件を使用して、元の配列からの位置に一致する行のみを確認します。さらにカスタマイズが必要な場合は

クエリ

WITH DataTable AS (
    SELECT 'key1' AS key, '<xml><entity><property type="alpha">123</property><property type="beta">abc</property><property type="delta">...</property></entity><entity><property type="alpha">321</property><property type="beta">cba</property><property type="delta">---</property></entity></xml>' AS xml UNION ALL 
    SELECT 'key2' AS key, '<xml><entity><property type="alpha">123</property><property type="beta">abc</property><property type="delta">...</property></entity><entity><property type="alpha">321</property><property type="beta">cba</property><property type="delta">---</property></entity></xml>' AS xml 
) 
SELECT 
    key, 
    alpha, 
    beta, 
    delta 
FROM DataTable 
LATERAL VIEW posexplode(xpath(xml, 'xml/entity/property[@type="alpha"]/text()')) xml_alpha AS pos_alpha, alpha 
LATERAL VIEW posexplode(xpath(xml, 'xml/entity/property[@type="beta"]/text()')) xml_beta AS pos_beta, beta 
LATERAL VIEW posexplode(xpath(xml, 'xml/entity/property[@type="delta"]/text()')) xml_delta AS pos_delta, delta 
WHERE pos_alpha = pos_beta 
AND pos_beta = pos_delta 
; 

結果が

key alpha beta delta 
0 key1 123 abc ... 
1 key1 321 cba --- 
2 key2 123 abc ... 
3 key2 321 cba --- 

を設定し、その後、あなたがそれらを必要とまったく同じ行を生成し、独自のカスタムUDTFを書いて考えるかもしれません。

+0

Chrisに感謝します。あなたの答えは正しいものであり、教育的です。非常に役に立ちました!今私はすべてのエンティティが "ベータ"のプロパティを持っているわけではないので、何とかこのようにOUTERのビューをまとめようとすると苦労しています。その場合、ベータのカラムにNULLが必要です。私はそれをもう少し試してみて、それを理解できなければ別の質問を投稿します。再度、感謝します。 – Ckratide

+0

@Ckratide、これを聞いてうれしい!あなたがより多くのカスタムロジックが必要な道にいるように思えます。私は自分のカスタムUDTFを書くことを検討したいという答えを編集しました。 https://cwiki.apache.org/confluence/display/Hive/DeveloperGuide+UDTF –

関連する問題