【问题标题】:How to pivot rows into columns in AWS Athena?如何将行转入 AWS Athena 中的列?
【发布时间】:2018-06-09 08:13:23
【问题描述】:

我是 AWS Athena 的新手,并试图将一些行转换为列,类似于此 StackOverflow post 中的最佳答案。

但是,当我尝试时:

SELECT column1, column2, column3
FROM data
PIVOT
(
  MIN(column3)
  FOR column2 IN ('VALUE1','VALUE2','VALUE3','VALUE4')
)

我收到错误: mismatched input '(' expecting {',', ')'} (service: amazonathena; status code: 400; error code: invalidrequestexception

有人知道如何在 AWS Athena 中实现我想要实现的目标吗?

【问题讨论】:

    标签: sql amazon-web-services pivot amazon-athena


    【解决方案1】:

    我在使用 PIVOT 函数时遇到了同样的问题。不过我用了一个转机的方式来获取一个类似格式的数据集:

    select 
      columnToGroupOn,
      min(if(colToPivot=VALUE1,column3,null)) as VALUE1, 
      min(if(colToPivot=VALUE2,column3,null)) as VALUE2, 
      min(if(colToPivot=VALUE3,column3,null)) as VALUE3 
    from
        data
    group by columnToGroupOn           
    

    【讨论】:

    • 我认为您应该使用“max”而不是“min”,因为在“if”表达式中,对于不匹配的行,您会返回 0。
    • 是的,你是对的,但是 OP 需要一个获取 min(column3) 的解决方案,而使用 max 则相反。我认为正确的解决方案是使用 null 而不是 0 作为默认值。更正了我的答案。
    【解决方案2】:

    您可以使用 map_agg 在 Athena 中创建单列 PIVOT

    SELECT
      uid,
      kv['c1'] AS c1,
      kv['c2'] AS c2,
      kv['c3'] AS c3
    FROM (
      SELECT uid, map_agg(key, value) kv
      FROM vtable
      GROUP BY uid
    ) t
    

    归功于this website。不幸的是,我还没有找到一种巧妙的方法来以这种方式进行多列旋转(我嵌套了查询,这并不漂亮)。

    【讨论】:

    • 这很有帮助。谢谢你。我想补充一点,map_agg() 函数中的键和值参数将是您要扩展的现有列,值将是与该列关联的值。例如键 = 物种,值 = 计数。
    • 该网址现已弃用,您可以尝试this website 获取文档。
    【解决方案3】:

    扩展@kadrach 的答案。 假设这样的表

    uid | key | value1 | value2
    ----+-----+--------+--------
     1  |  A  |  10    | 1000
     1  |  B  |  20    | 2000
     2  |  A  |  11    | 1001
     2  |  B  |  21    | 2001
    

    单列 PIVOT 是这样工作的

    SELECT
      uid,
      kv1['A'] AS A_v1,
      kv1['B'] AS B_v1
    FROM (
      SELECT uid, map_agg(key, value1) kv1
      FROM vtable
      GROUP BY uid
    ) 
    

    结果:

    uid | A_v1 | B_v1 
    ----+------+-------
     1  |  10  |  20   
     2  |  11  |  21  
    
    

    多列 PIVOT 是这样工作的

    SELECT
      uid,
      kv1['A'] AS A_v1,
      kv1['B'] AS B_v1,
      kv2['A'] AS A_v2,
      kv2['B'] AS B_v2
    FROM (
      SELECT uid,
          map_agg(key, value1) kv1,
          map_agg(key, value2) kv2
      FROM vtable
      GROUP BY uid
    ) 
    

    结果:

    uid | A_v1 | B_v1 | A_v2 | B_v2 
    ----+------+------+------+-----
     1  |  10  |  20  | 1000 | 2000
     2  |  11  |  21  | 1001 | 2001
    
    

    【讨论】:

    • 这是否意味着我必须提前知道key 列中的所有唯一值?
    • 不幸的是,这种方法是可以的。当然可能有更通用的解决方案(例如使用连接),但我还没有创建它的需要。
    • 我试图找到一个通用的解决方案,它允许根据值动态创建列数 - 但 presto 似乎没有提供这样的东西。我的解决方法是根据初始查询的结果动态创建相应的 SQL。但这总是被证明太麻烦了,在我们的例子中,我们总是新的几个可能的值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-04
    • 2021-12-07
    • 2021-02-18
    • 2021-09-17
    • 1970-01-01
    • 1970-01-01
    • 2022-08-13
    相关资源
    最近更新 更多