SQL Server多表关联去重:获取指定格式的合并查询结果
解决SQL Server多表左关联笛卡尔积重复问题
完全可以实现需求,你遇到的重复是因为关联的子表(Tbl_Production、Tbl_Adjusment、Tbl_Assembly)中,同一(ProdCode,Batchno)存在多条记录,左关联后不同子表的记录两两组合产生了笛卡尔积。以下是三种常用解决方案:
方案一:聚合函数分组去重
如果需要将子表中同一批次的多条记录合并为汇总值(如总和、最大值),可以用GROUP BY结合聚合函数实现:
SELECT p.ProdCode, p.Batchno, -- 按业务需求聚合生产表数据,比如汇总数量 ISNULL(SUM(prod.Qty), 0) AS TotalProductionQty, -- 汇总调整表的调整数量 ISNULL(SUM(adj.AdjustQty), 0) AS TotalAdjustmentQty, -- 取组装表的最新状态(假设有CreateTime字段) ISNULL(MAX(asm.AssemblyStatus), '未组装') AS LatestAssemblyStatus FROM Tbl_Product p LEFT JOIN Tbl_Production prod ON p.ProdCode = prod.ProdCode AND p.Batchno = prod.Batchno LEFT JOIN Tbl_Adjusment adj ON p.ProdCode = adj.ProdCode AND p.Batchno = adj.Batchno LEFT JOIN Tbl_Assembly asm ON p.ProdCode = asm.ProdCode AND p.Batchno = asm.Batchno GROUP BY p.ProdCode, p.Batchno;
方案二:APPLY关联子查询取单条记录
如果需要从每个子表中提取特定单条记录(比如最新创建的),OUTER APPLY比普通左关联更灵活,能直接避免笛卡尔积:
SELECT p.ProdCode, p.Batchno, prod.Qty AS LatestProductionQty, adj.AdjustQty AS LatestAdjustmentQty, asm.AssemblyStatus AS LatestAssemblyStatus FROM Tbl_Product p -- 取该批次最新的生产记录 OUTER APPLY ( SELECT TOP 1 Qty FROM Tbl_Production WHERE ProdCode = p.ProdCode AND Batchno = p.Batchno ORDER BY CreateTime DESC -- 替换为实际排序字段,比如操作时间 ) prod -- 取该批次最新的调整记录 OUTER APPLY ( SELECT TOP 1 AdjustQty FROM Tbl_Adjusment WHERE ProdCode = p.ProdCode AND Batchno = p.Batchno ORDER BY CreateTime DESC ) adj -- 取该批次最新的组装记录 OUTER APPLY ( SELECT TOP 1 AssemblyStatus FROM Tbl_Assembly WHERE ProdCode = p.ProdCode AND Batchno = p.Batchno ORDER BY CreateTime DESC ) asm;
方案三:合并子表多条记录为字符串(SQL Server 2017+)
如果需要把子表中同一批次的多条记录值合并为单个字符串(比如用逗号分隔),可以用STRING_AGG函数:
SELECT p.ProdCode, p.Batchno, ISNULL(STRING_AGG(prod.Qty, ', '), '') AS ProductionQtyList, ISNULL(STRING_AGG(adj.AdjustQty, ', '), '') AS AdjustmentQtyList FROM Tbl_Product p LEFT JOIN Tbl_Production prod ON p.ProdCode = prod.ProdCode AND p.Batchno = prod.Batchno LEFT JOIN Tbl_Adjusment adj ON p.ProdCode = adj.ProdCode AND p.Batchno = adj.Batchno GROUP BY p.ProdCode, p.Batchno;
关键注意事项
- 关联时必须同时匹配
ProdCode和Batchno两个联合主键字段,避免因关联条件不全导致的笛卡尔积; - 根据实际业务需求选择对应方案,比如需要汇总就用聚合,需要单条记录就用APPLY,需要合并字符串就用
STRING_AGG。
内容的提问来源于stack exchange,提问作者Bambang Setiawan
相关产品推荐
相关产品推荐

