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

SQL SUM计算返回重复行而非单一求和结果的技术求助

解决SQL查询返回重复总和记录的问题

我来帮你分析下问题根源,再给出适配不同需求的解决方案:

你之所以得到大量重复记录,是因为用了sum() over ()这种无分区的窗口函数——它会为查询结果里的每一行都计算整个结果集的总和。而你的多表JOIN操作会返回多条匹配行,所以每一行都会重复显示相同的总和值,自然就出现了重复记录。

方案1:仅获取全局总求和值(不需要分支名称)

如果你的目标只是得到两个列的总求和,不需要b.[Name],直接用普通聚合函数即可,完全不需要窗口函数:

SELECT 
    SUM(td.detailNumber) AS Totaldetail, 
    SUM(t.Original) AS TotalOriginal 
FROM Detail td WITH(NOLOCK)
INNER JOIN Ticket t WITH(NOLOCK) ON t.ID = td.ID
INNER JOIN [system].Branch b WITH(NOLOCK) ON t.BranchID = b.BranchID
INNER JOIN [Option] mo WITH(NOLOCK) ON mo.OptionID = td.MID  -- 补全表别名,避免列名歧义
WHERE (td.ResultDateTime >= '2018/03/10 00:00:00:000' AND td.ResultDateTime <= '你的结束时间')

方案2:按分支分组获取每个分支的求和值

如果需要同时看到每个分支的名称和该分支对应的求和值,用GROUP BY分组聚合就可以了:

SELECT 
    b.[Name],
    SUM(td.detailNumber) AS Totaldetail, 
    SUM(t.Original) AS TotalOriginal 
FROM Detail td WITH(NOLOCK)
INNER JOIN Ticket t WITH(NOLOCK) ON t.ID = td.ID
INNER JOIN [system].Branch b WITH(NOLOCK) ON t.BranchID = b.BranchID
INNER JOIN [Option] mo WITH(NOLOCK) ON mo.OptionID = td.MID
WHERE (td.ResultDateTime >= '2018/03/10 00:00:00:000' AND td.ResultDateTime <= '你的结束时间')
GROUP BY b.[Name]

方案3:同时显示分支名称和全局总求和值

如果需求是既看到每个分支的名称,又看到整个结果集的总求和(不是每个分支的),可以用两种方式实现:

方法A:用DISTINCT快速去重

通过DISTINCT过滤掉重复的总和记录:

SELECT DISTINCT
    b.[Name],
    SUM(td.detailNumber) OVER () AS Totaldetail, 
    SUM(t.Original) OVER () AS TotalOriginal 
FROM Detail td WITH(NOLOCK)
INNER JOIN Ticket t WITH(NOLOCK) ON t.ID = td.ID
INNER JOIN [system].Branch b WITH(NOLOCK) ON t.BranchID = b.BranchID
INNER JOIN [Option] mo WITH(NOLOCK) ON mo.OptionID = td.MID
WHERE (td.ResultDateTime >= '2018/03/10 00:00:00:000' AND td.ResultDateTime <= '你的结束时间')

方法B:子查询拆分逻辑(更清晰)

先单独计算全局总求和,再关联去重后的分支名称,逻辑更直观:

SELECT 
    branch_names.[Name],
    global_totals.Totaldetail,
    global_totals.TotalOriginal
FROM (
    -- 单独计算全局总求和
    SELECT 
        SUM(td.detailNumber) AS Totaldetail, 
        SUM(t.Original) AS TotalOriginal 
    FROM Detail td WITH(NOLOCK)
    INNER JOIN Ticket t WITH(NOLOCK) ON t.ID = td.ID
    INNER JOIN [Option] mo WITH(NOLOCK) ON mo.OptionID = td.MID
    WHERE (td.ResultDateTime >= '2018/03/10 00:00:00:000' AND td.ResultDateTime <= '你的结束时间')
) AS global_totals
CROSS JOIN (
    -- 获取符合条件的唯一分支名称
    SELECT DISTINCT b.[Name]
    FROM Detail td WITH(NOLOCK)
    INNER JOIN Ticket t WITH(NOLOCK) ON t.ID = td.ID
    INNER JOIN [system].Branch b WITH(NOLOCK) ON t.BranchID = b.BranchID
    INNER JOIN [Option] mo WITH(NOLOCK) ON mo.OptionID = td.MID
    WHERE (td.ResultDateTime >= '2018/03/10 00:00:00:000' AND td.ResultDateTime <= '你的结束时间')
) AS branch_names

最后提个小细节:你原来的SQL里INNER JOIN Option mo WITH(NOLOCK) ON OptionID = td.MID这里,OptionID前面最好加上表别名mo.,否则如果其他关联表也有同名的OptionID列,会触发列名歧义错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:16:56