如何用 'as' 子句修复 'must be an aggregate expression or appear in GROUP BY clause'

How to fix 'must be an aggregate expression or appear in GROUP BY clause' with 'as' clause

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

我在 sample_db

this Link 的指导下创建了 cloudfront_logs table

下面是我为按小时获取请求数所做的查询

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;

然而它 returns 像这样的错误

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;

终于,我得到了结果。

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

看来 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);

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;