SQL - 聚合可能不会出现在 WHERE 子句中,除非它位于 HAVING 子句中包含的子查询中

Posted

技术标签:

【中文标题】SQL - 聚合可能不会出现在 WHERE 子句中,除非它位于 HAVING 子句中包含的子查询中【英文标题】:SQL - An aggregate may not appear in the WHERE clause unless it is in a subquery contained in a HAVING clause 【发布时间】:2021-04-05 17:06:00 【问题描述】:

如果您看到下图,我只想查看平均收入高于总体平均水平的那些类别。

我正在使用的查询如下。最后一行导致了问题。

WITH cte_avg AS (
    SELECT P.prod_cat, Avg_revenue = AVG(CAST(T.total_amt AS NUMERIC))
    FROM [dbo].[Transactions] AS T
    LEFT JOIN [dbo].[prod_cat_info] AS P ON T.prod_cat_code=P.prod_cat_code
    GROUP BY P.prod_cat
)
SELECT prod_cat, Avg_revenue
FROM cte_avg
WHERE Avg_revenue > AVG(Avg_revenue)

我得到的错误是:

聚合可能不会出现在 WHERE 子句中,除非它出现在 HAVING 子句或选择列表中包含的子查询中,并且被聚合的列是外部引用。

请告诉我如何解决这个问题。谢谢!

【问题讨论】:

这能回答你的问题吗? An aggregate may not appear in the WHERE clause unless it is in a subquery 【参考方案1】:

我认为您要编写的查询类似于:

select p.prod_cat, t.avg_total_amount
from (
    select prod_cat_code, avg(total_amount) as avg_total_amount
    from transactions
    group by prod_cat_code
    having avg(total_amount) > (select avg(total_amount) from transactions)
) t
inner join prod_cat_info p on p.prod_cat_code = t.prod_cat_code

子查询按类别聚合交易,计算平均值,并将其与整体交易平均值进行比较。然后我们只需将类别表与连接一起带入。

【讨论】:

【参考方案2】:

我建议使用窗口函数。目前尚不清楚您所说的“平均总收入”是什么意思。如果您指的是产品总收入的平均值,那么:

SELECT *
FROM (SELECT P.prod_cat, SUM(total_amount) as total_revenue,
             AVG(SUM(total_amount)) OVER () as avg_total_revenue
      FROM [dbo].[Transactions] T JOIN
           [dbo].[prod_cat_info] P
            ON T.prod_cat_code=P.prod_cat_code
      GROUP BY P.prod_cat
     ) c
WHERE total_revenue > avg_total_revenue;

如果您指的是产品平均值与总体平均值相比:

SELECT *
FROM (SELECT P.prod_cat, AVG(total_amount) as avg_revenue,
             SUM(SUM(total_amount)) OVER () / SUM(COUNT(*)) as avg_total_revenue
      FROM [dbo].[Transactions] T JOIN
           [dbo].[prod_cat_info] P
            ON T.prod_cat_code=P.prod_cat_code
      GROUP BY P.prod_cat
     ) c
WHERE avg_revenue > avg_total_revenue

【讨论】:

【参考方案3】:

以下查询解决了我的问题。

WITH cte_avg AS (SELECT P.prod_cat, Avg_revenue = AVG(CAST(T.total_amt AS NUMERIC))
    FROM [dbo].[Transactions] AS T
    LEFT JOIN [dbo].[prod_cat_info] AS P ON T.prod_cat_code=P.prod_cat_code
    GROUP BY P.prod_cat)
    SELECT prod_cat, Avg_revenue
    FROM cte_avg
    WHERE Avg_revenue>(SELECT AVG(Avg_revenue) FROM cte_avg)

【讨论】:

以上是关于SQL - 聚合可能不会出现在 WHERE 子句中,除非它位于 HAVING 子句中包含的子查询中的主要内容,如果未能解决你的问题,请参考以下文章

如何修复where子句中的聚合?

SQL WHERE 子句中的聚合函数

DB2中where子句中用了1=1的话,会不会导致索引失效,请详细说明.

SQL语句中,为啥where子句不能使用列别名,而order by却可以?

SQL内外连

SQL 选择除最近日期之外的所有内容