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
相关产品推荐
相关产品推荐

