如何有效取消Hive中的多个列?

时间:2018-11-20 16:27:19

标签: hive query-optimization hiveql unpivot

我的数据的结构如下表所示:

| Name | Foo_A | Foo_B | Foo_C | Bar_A | Bar_B | Bar_C |
--------------------------------------------------------
| abcd |    16 |    32 |    14 |    52 |    41 |    17 |
| ...  |   ... |   ... |   ... |   ... |   ... |   ... |

我希望以类似以下方式查询Hive中的数据:

| Name | Class | FooVal | BarVal |
----------------------------------
| abcd | A     |     16 |     52 |
| abcd | B     |     32 |     41 |
| abcd | C     |     14 |     17 |
| ...  | ...   |    ... |    ... |

我已经知道并正在使用UNION ALL,但是使用“横向视图爆炸”地图数据类型可以更有效地实现此目的?

3 个答案:

答案 0 :(得分:0)

使用class stack进行交叉联接(请参见代码示例)将主表行x3乘以每class的一行,然后使用case语句来派生列,具体取决于class值。具有小数据集(3行)的CROSS JOIN应该转换为 map join ,并且将在映射器上非常快速地执行。

set hive.auto.convert.join=true; --this enables map-join

select t.Name,
       s.class,
       case s.class when 'A' then t.Foo_A 
                    when 'B' then t.foo_B
                    when 'C' then t.foo_C
        end as FooVal,
       case s.class when 'A' then t.Bar_A 
                    when 'B' then t.Bar_B
                    when 'C' then t.Bar_C
        end as BarVal              
 from table t 
      cross join (select stack(3,'A','B','C') as class) s
;

它只会扫描表一次,并且比UNION ALL方法的性能要好得多。

答案 1 :(得分:0)

感谢您的回复!请在下面找到比CROSS JOIN更快的另一种方式。

    select t1.ID, t2.key_1 as class, t2.FooVal, t3.BarVal
    from table t1
    LATERAL VIEW explode (map(
   'A', Foo_A,
   'B', Foo_B,
   'C', Foo_C
    )) t2 as key_1, FooVal
    LATERAL VIEW explode (map(
    'A', Bar_A,
    'B', Bar_B,
    'C', Bar_C
     )) t3 as key_2, BarVal
     where t2.key_1 = t3.key_2;

答案 2 :(得分:0)

配置单元取消多列显示:

select
        t1.ID,
        lv.key         as class,
        lv.FooStr.col1 as FooVal,
        lv.FooStr.col2 as BarVal
    from
        table t1
        LATERAL VIEW explode (
            map(
               'A', named_struct('col1', Foo_A, 'col2', Bar_A),
               'B', named_struct('col1', Foo_B, 'col2', Bar_B),
               'C', named_struct('col1', Foo_C, 'col2', Bar_C)
                )) lv as key, FooStr
    where
        coalesce(lv.FooStr.col1, lv.FooStr.col2) IS NOT NULL