You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL查询使用双聚合函数:生成含DIFF的INVOICE表查询求助

解决SQL查询中DIFF字段的问题

嘿,刚入门SQL碰到这种细节问题太正常啦,我来帮你搞定~

首先得先搞清楚你要的DIFF字段到底是什么:从你的描述来看,应该是每条发票的金额和整张表平均发票金额的差值对吧?那你之前用SUM(INV_AMOUNT - AVG(INV_AMOUNT))的问题在于,这个表达式会把所有行的差值加起来,而数学上这个总和永远是0(因为所有金额的总和等于平均值乘以行数,相减后总和为0),这肯定不是你想要的结果。

方法一:基于你现有语句修改

你已经写出了获取平均金额的子查询,直接在SELECT里用当前行的INV_AMOUNT减去这个平均值就行,不用加SUM:

SELECT 
    INV_NUM, 
    INV_AMOUNT, 
    (SELECT AVG(INV_AMOUNT) FROM INVOICE) AS AVG_INV,
    INV_AMOUNT - (SELECT AVG(INV_AMOUNT) FROM INVOICE) AS DIFF
FROM INVOICE;

这样每条记录都会显示自己的金额与整体平均值的差值,完全符合你的需求。

方法二:用窗口函数更优雅(推荐)

如果你的数据库支持窗口函数(比如MySQL 8.0+、PostgreSQL、SQL Server等),可以用AVG() OVER()来一次性计算全局平均值,不用重复写子查询,代码更简洁,效率也更高:

SELECT 
    INV_NUM, 
    INV_AMOUNT,
    AVG(INV_AMOUNT) OVER() AS AVG_INV,
    INV_AMOUNT - AVG(INV_AMOUNT) OVER() AS DIFF
FROM INVOICE;

AVG(INV_AMOUNT) OVER()会计算整个INVOICE表的平均金额,并且把这个值赋给每一行,这样直接做减法就能得到每条记录的差值。

为什么你的原写法不行?

再啰嗦两句帮你理解:SUM(INV_AMOUNT - AVG(INV_AMOUNT))本质是把所有行的(金额-平均值)加起来,而根据平均值的定义:
SUM(INV_AMOUNT) = AVG(INV_AMOUNT) * COUNT(*)
所以代入后:
SUM(INV_AMOUNT - AVG) = SUM(INV_AMOUNT) - COUNT(*) * AVG = 0
这个结果对单条记录来说没有意义,所以才会不符合你的预期~

内容的提问来源于stack exchange,提问作者Sudodl09

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:13:58