【问题标题】:Impala - transform columns to rows without using UNION ALLImpala - 将列转换为行而不使用 UNION ALL
【发布时间】:2017-02-01 04:02:43
【问题描述】:

我有一个包含用户和每周活动的表格,例如这是user_activity 表格:

userid | wk1 | wk2 | wk3
u1     |  1  |  0  |  1
u2     |  0  |  1  |  0
u3     |  1  |  0  |  1

我想把它改成:

week   | active
wk1    |   2
wk2    |   1
wk3    |   2

我可以像这样使用 UNION ALL 来实现这一点:

SELECT 'wk1' as week,
       SUM( wk1 ) AS active
FROM user_activity
UNION ALL
SELECT 'wk2' as week,
       SUM( wk2 ) AS active
FROM user_activity
UNION ALL
SELECT 'wk3' as week,
       SUM( wk3 ) AS active
FROM user_activity;

有没有办法在不使用 UNION ALL 的情况下达到同样的效果?

谢谢!

编辑: Impala 版本:2.6.0

没有 UNION ALL 的原因:对于每个 SELECT,将从 HDFS 扫描整个表。如果我有一个巨大的表,这将导致 OOM 错误。

【问题讨论】:

  • 为什么没有 UNION ALL?
  • 除非您有一个表,其中的值“wk1”、“wk2”和“wk3”在不同的行中,否则您需要构造这样的表。 UNION ALL 似乎是最有可能的方法。
  • Impala 版本?

标签: sql impala


【解决方案1】:

这应该可以解决您的性能问题。
该表仅被扫描一次。
记录没有被复制 X3。
UNION ALL 在这里仅用于单个记录。

select  concat('wk',cast(c.i as string))    as week
       ,case c.i 
            when 1 then wk1 
            when 2 then wk2
            when 3 then wk3
        end                 as active

from   (select  sum(wk1) AS wk1
               ,sum(wk2) AS wk2
               ,sum(wk3) AS wk3 

        from    user_activity
        ) t

        cross join (            select 1 as i
                    union all   select 2 
                    union all   select 3
                    ) c
;                    

+------+--------+
| week | active |
+------+--------+
| wk1  | 2      |
| wk2  | 1      |
| wk3  | 2      |
+------+--------+

【讨论】:

  • 你们太棒了!!
【解决方案2】:

您可以尝试反透视和聚合。这样 user_activity 表只会被读取一次。

select
    w.week,
    sum(case w.week 
        when 'wk1' then wk1
        when 'wk2' then wk2
        when 'wk3' then wk3
    end) active
from user_activity u
cross join (
    select 'wk1' week union all
    select 'wk2' week union all
    select 'wk3' week 
) w group by w.week;

生产:

+------+--------+
| week | active |
+------+--------+
| wk1  | 2      |
| wk2  | 1      |
| wk3  | 2      |
+------+--------+

它只需要一个聚合而不是三个。我使用UNION ALL 仅用于构建自定义数据透视查询。我没有在用户表上使用它。

【讨论】:

  • 感谢您向新方向提出想法 +1
【解决方案3】:

忽略琐碎的“使用UNION”,这个问题似乎有点荒谬。但这里有一种方法:

with nounionall as (
      select (case row_number() over (order by userid)
                  when 1 then 'wk1'
                  when 2 then 'wk2'
                  when 3 then 'wk3'
              end) as week
      from user_activity ua
      limit 3
     )
select nounionall.week,
       sum(case when nounionall.week = 'wk1' then wk1
                when nounionall.week = 'wk2' then wk2
                when nounionall.week = 'wk3' then wk3
           end) as actives
from nounionall cross join
     user_activity ua
group by nounionall.week

【讨论】:

  • 感谢您向新方向提出想法 +1。
【解决方案4】:

这个没有任何联合的非常简单的解决方案怎么样:-

SELECT [week],active
FROM (
    SELECT SUM(wk1)wk1,SUM(wk2)wk2,SUM(wk3)wk3
    FROM user_activity)pvt
UNPIVOT ([active] FOR [Week] IN  (wk1,wk2,wk3)) unpvt

【讨论】:

  • 不幸的是,我认为 Impala 不支持 UNPIVOT。谢谢。
  • 随时欢迎。 :)
猜你喜欢
  • 2015-07-03
  • 1970-01-01
  • 2017-06-11
  • 1970-01-01
  • 2016-04-18
  • 1970-01-01
  • 2021-11-14
  • 1970-01-01
  • 2020-06-20
相关资源
最近更新 更多