如何使用另一个平面/简单配置单元表中的map [structs]加载配置单元表

时间:2014-10-16 11:35:54

标签: json hadoop map struct hive

我在hive中有2个表有Order和Order_Detail(有1:n关系,并且在order_id上加入),我试图加载到单个表中,利用hive复杂数据类型 - map [struct]。

说ORDER有以下数据,

Order_id total_amount客户

123 10.00 1

456 12.00 2

和ORDER_DETAILS有

Order_id Order_Item_id Item_amount Item_type

123 1 5.00 A

123 2 5.00 B

456 1 6.00 A

456 2 3.00 B

456 3 3.00 C

我想创建单表ORDERS,所有订单列和order_detail列作为结构图的映射。 这有助于我将相关数据和查询组合在一起,从而避免频繁的连接。 我尝试使用输入相应serde的txt / json文件来加载具有复杂数据类型的表,并且它运行良好。 但在这种情况下,我想将现有的2个ORCFile格式的hive表中的数据加载到新表中。尝试过使用named_struct函数的一些基本插入,但它分别加载每一行,并没有将相同的order_id组合成一行。

预期输出类似,

123 10.00 1 [1:{5.00,A},2:{5.00,B}]

456 12.00 2 {1:{6.00,A},2:{3.00,B},3:{3.00,C}]

但是我明白了,

123 10.00 1 [1:{5.00,A}]

123 10.00 1 [2:{5.00,B}]

456 12.00 2 {1:{6.00,A}]

456 12.00 2 {2:{3.00,B}]

456 12.00 2 {3:{3.00,C}]

请帮助我理解通过INSERT INTO表选择2个表来实现这一目标的方法。 提前谢谢。

1 个答案:

答案 0 :(得分:3)

我找到了一种使用map,named_struct函数和David Worms在to_map UDF blog上发布的自定义UDF to_map的方法。 这是样本,

CREATE TABLE ORDER(
  order_id bigint,
  total_amount bigint,
  customer bigint)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat';

CREATE TABLE ORDER_DETAILS(
  order_id bigint,
  Order_Item_id bigint,
  Item_amount bigint,
  Item_type string)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS INPUTFORMAT
  'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat';

CREATE TABLE ORDERS(
  order_id bigint,
  Order_Items map < bigint, struct < Item_amount: bigint, Item_type: string >> ,
  total_amount bigint,
  customer bigint)
ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.orc.OrcSerde'
STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.orc.OrcInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat';

Insert overwrite table ORDERS
select
a.order_id,
  a.order_items,
  b.total_amount,
  b.customer
from
  (select order_id as order_id,
    to_map(order_item_id, named_struct("item_amount", item_amount, "item_type", item_type)) as order_items from ORDER_DETAILS group by order_id) a
JOIN ORDER b ON(a.order_id = b.order_id);

从ORDERS中选择*;

123 {1:{“Item_amount”:5,“Item_type”:“A”},2:{“Item_amount”:5,“Item_type”:“B”}} 10 1

456 {1:{“Item_amount”:6,“Item_type”:“A”},2:{“Item_amount”:3,“Item_type”:“B”},3:{“Item_amount”:3, “Item_type”:“C”}} 12 2

希望这有助于每个人。