【问题标题】:How to fix 'must be an aggregate expression or appear in GROUP BY clause' with 'as' clause如何使用“as”子句修复“必须是聚合表达式或出现在 GROUP BY 子句中”
【发布时间】:2019-10-16 20:38:54
【问题描述】:

我正在尝试使用 athena 查询按小时获取 CloudFront 分配的请求数。

我在我的 sample_db 中创建了由 this Link 引导的 cloudfront_logs 表

以下是我按小时获取请求数的查询

SELECT date_trunc('hour',from_iso8601_timestamp(concat(concat(date_format(date, '%Y-%m-%d'), 'T'), time))) as TIME, count(*) as CNT
FROM "sample_db"."cloudfront_logs" 
WHERE 
    from_iso8601_timestamp(concat(concat(date_format(date, '%Y-%m-%d'), 'T'), time)) >= from_iso8601_timestamp('2019-05-29T00:00:00')
AND 
    from_iso8601_timestamp(concat(concat(date_format(date, '%Y-%m-%d'), 'T'), time)) < from_iso8601_timestamp('2019-05-30T00:00:00')
GROUP BY TIME
ORDER BY TIME ASC;

但是它会返回这样的错误

SYNTAX_ERROR: line 2:8: '"date_trunc"('hour', "from_iso8601_timestamp"("concat"("concat"("date_format"("date", '%Y-%m-%d'), 'T'), "time")))' must be an aggregate expression or appear in GROUP BY clause

因此,我将GROUP BY之后的TIME替换为date_trunc('hour',from_iso8601_timestamp(concat(concat(date_format(date, '%Y-%m-%d'), 'T'), time))),并再次尝试。

SELECT date_trunc('hour',from_iso8601_timestamp(concat(concat(date_format(date, '%Y-%m-%d'), 'T'), time))) as TIME, count(*) as CNT
FROM "sample_db"."cloudfront_logs" 
WHERE 
    from_iso8601_timestamp(concat(concat(date_format(date, '%Y-%m-%d'), 'T'), time)) >= from_iso8601_timestamp('2019-05-29T00:00:00')
AND 
    from_iso8601_timestamp(concat(concat(date_format(date, '%Y-%m-%d'), 'T'), time)) < from_iso8601_timestamp('2019-05-30T00:00:00')
GROUP BY date_trunc('hour',from_iso8601_timestamp(concat(concat(date_format(date, '%Y-%m-%d'), 'T'), time)))
ORDER BY TIME ASC;

终于,我得到了结果。

我认为,它也应该适用于第一个查询。我可以就第一个查询获得任何建议吗?因为它看起来更简单。

【问题讨论】:

    标签: sql group-by presto amazon-athena


    【解决方案1】:

    Athena 基于 Presto。在 Presto 中,您不能在 GROUP BY 子句中使用 SELECT 子句列别名。 但是,您可以使用相同的表达式,例如:

    SELECT some_expression(a) FROM ... GROUP BY some_expression(a)
    

    此外,您可以使用它们在 SELECT 列表中的位置来引用 SELECT 子句列:

    SELECT some_expression(a) FROM ... GROUP BY 1
    

    这是 ANSI SQL 标准语法。模式详情见Presto GROUP BY documentation

    这也可以在ORDER BY 中使用,因此您的查询类似于

    SELECT date_trunc('hour',from_iso8601_timestamp(concat(concat(date_format(date, '%Y-%m-%d'), 'T'), time))) as TIME, count(*) as CNT
    FROM "sample_db"."cloudfront_logs" 
    WHERE ...
    GROUP BY 1
    ORDER BY 1 ASC;
    

    【讨论】:

      【解决方案2】:

      这只是似乎 Athena SQL 没有使 SELECT 子句中使用的别名在同一级别的 GROUP BY 子句中可用。但是,许多版本的 SQL 确实允许这样做。您可以尝试在此处使用 CTE 以减少冗长:

      WITH cte AS (
          SELECT from_iso8601_timestamp(concat(concat(date_format(date, '%Y-%m-%d'), 'T'), time)) AS ts
          FROM "sample_db"."cloudfront_logs"
      )
      
      SELECT
          DATE_TRUNC('hour', ts) AS TIME,
          COUNT(*) AS CNT
      FROM cte
      WHERE
          ts >= from_iso8601_timestamp('2019-05-29T00:00:00') AND
          ts <  from_iso8601_timestamp('2019-05-30T00:00:00')
      GROUP BY
          DATE_TRUNC('hour', ts)
      ORDER BY
          DATE_TRUNC('hour', ts);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-05
        • 2013-08-06
        • 2015-08-14
        • 2018-05-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多