如何有效地取消 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
我的数据结构如下 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