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

How to efficiently unpivot MULTIPLE columns in Hive?

我的数据结构如下 table:

| 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,但是使用 "LATERAL VIEW explode" 地图数据类型执行此操作的更有效方法是什么?

CROSS JOIN with class stack(参见代码示例)将乘以主 table 行 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
;

它将只扫描 table 一次,并且比 UNION ALL 方法执行得更好。

感谢回复!请在下面找到另一种比 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;

Hive 逆透视多个列:

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