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

SQL Server按条件删除重复行及采购订单求和异常求助

解决SQL多表连接求和重复+保留最新采购订单记录的问题

嘿,我完全懂你现在的头疼——刚学SQL的时候,多表连接和分组求和的坑真的很容易踩!你遇到的核心问题是未指定连接条件的左连接+多对多关系导致的笛卡尔积,再加上GROUP BY的错误,直接把求和结果放大了N倍。

先给你梳理下问题根源:

  • 你的原查询里所有LEFT JOIN都没写ON子句,这会让数据库把每个表的所有行互相连接,产生大量重复数据;
  • 就算有连接条件,一个采购订单对应多条产品行(Table A的行),连接后每条产品行都会带上采购订单的信息,SUM的时候就把同一个PO的金额加了好几次;
  • 还有个小错误:GROUP BY里包含了A.column2,但你明明要SUM这个字段,这会让分组变细,求和结果根本不是你想要的总额。

接下来给你一个修正后的方案,核心思路是先把重复的采购订单记录过滤掉,只保留每个PO的最新日期行,再和其他表连接求和:

-- 先定义CTE,筛选每个采购订单的最新日期记录
WITH LatestPurchaseOrders AS (
    SELECT 
        B.Purchase_Order,
        C.Date_Purchase_Order,
        -- 这里可以加上B/C表中你需要的其他字段
        -- 按采购订单分组,按采购日期倒序排,最新的行rn=1
        ROW_NUMBER() OVER (PARTITION BY B.Purchase_Order ORDER BY C.Date_Purchase_Order DESC) AS rn
    FROM Table B
    -- 替换成B和C的实际连接条件,比如B.po_id = C.po_id
    LEFT JOIN Table C ON B.purchase_order_id = C.purchase_order_id
)
SELECT 
    A.column1, 
    SUM(A.column2) AS total_column2, -- 给求和字段起个清晰的别名
    LPO.Purchase_Order, 
    LPO.Date_Purchase_Order, 
    D.Invoice_Number, 
    D.Date_Payment_Invoice, 
    E.column7,
    -- 现在每个PO只出现一次,这个计数会更准确,如果需要按A.column1统计重复可以保留
    ROW_NUMBER() OVER (PARTITION BY A.column1 ORDER BY A.column1) AS Count_Duplicates
FROM Table A
-- 替换成A和B的实际连接条件,比如A.related_po_id = B.purchase_order_id
LEFT JOIN Table B ON A.related_po_id = B.purchase_order_id
-- 只连接每个PO的最新记录
LEFT JOIN LatestPurchaseOrders LPO ON B.Purchase_Order = LPO.Purchase_Order AND LPO.rn = 1
-- 替换成B/D的实际连接条件
LEFT JOIN Table D ON B.purchase_order_id = D.purchase_order_id
-- 替换成D/E的实际连接条件
LEFT JOIN Table E ON D.invoice_id = E.invoice_id
-- GROUP BY里不能包含A.column2,因为你要SUM它!只分组非聚合字段
GROUP BY 
    A.column1, 
    LPO.Purchase_Order, 
    LPO.Date_Purchase_Order, 
    D.Invoice_Number, 
    D.Date_Payment_Invoice, 
    E.column7

几个关键要点:

  • 用LatestPurchaseOrders这个CTE提前过滤掉采购订单的旧记录,只留最新的那条,这样连接后每个PO只会出现一次,不会和产品行重复相乘;
  • 所有JOIN必须加上ON子句,指定表之间的关联键,这是避免笛卡尔积的核心;
  • GROUP BY里移除了A.column2,因为聚合函数SUM的字段不能出现在GROUP BY里(除非你就是要按每个column2值分组,但显然你不是);
  • 如果发票(Table D)也存在一个PO对应多条发票的情况,你可以用同样的CTE逻辑处理,只保留每个发票的最新付款日期。

这样处理后,求和的金额就会是正确的$1000,而不是$10000,同时单个记录的PO也会被保留下来。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:55:34