SSMS报表生成:多表关联因UniqueID对应双值导致重复行问题求助
这种情况我做报表的时候碰过好多次,属于关联查询里非常典型的重复行问题,给你几个针对性的解决方案,你可以根据自己的报表需求来选:
方案1:只保留单一状态的数据(适合报表只需'in'或'out'其中一种)
如果你的报表不需要同时展示两种状态的信息,那最简单的办法就是在关联那张状态表的时候,直接加个过滤条件,只取你需要的状态值。比如原来的关联语句是:
JOIN 你的状态表 s ON 主表.UniqueID = s.UniqueID
改成:
JOIN 你的状态表 s ON 主表.UniqueID = s.UniqueID AND s.状态字段 = 'in' -- 或者 'out',看你需要哪个
这样就不会因为同一个UniqueID有两种状态而产生重复行了。
方案2:行转列,把'in'/'out'转为单独列(适合需要同时展示两种状态)
如果报表需要同时呈现'in'和'out'对应的字段值,那把行数据转成列是最优解,这样同一个UniqueID只会显示一行。用SQL Server的CASE语句就能轻松实现:
SELECT 主表.UniqueID, 主表.字段A, 主表.字段B, -- 提取'in'状态对应的字段值 MAX(CASE WHEN s.状态字段 = 'in' THEN s.目标字段 ELSE NULL END) AS in_字段值, -- 提取'out'状态对应的字段值 MAX(CASE WHEN s.状态字段 = 'out' THEN s.目标字段 ELSE NULL END) AS out_字段值 FROM 主表 JOIN 你的状态表 s ON 主表.UniqueID = s.UniqueID -- 按主表的唯一标识和其他非重复字段分组 GROUP BY 主表.UniqueID, 主表.字段A, 主表.字段B
如果你习惯用SSMS的可视化工具,也可以在查询设计器里添加这些CASE表达式,然后设置分组依据为主表的UniqueID和其他不需要重复的字段。
另外,SQL Server的PIVOT函数也能实现类似效果,写法更简洁:
SELECT * FROM ( -- 先把需要的字段都查出来,作为数据源 SELECT 主表.UniqueID, 主表.字段A, 主表.字段B, s.状态字段, s.目标字段 FROM 主表 JOIN 你的状态表 s ON 主表.UniqueID = s.UniqueID ) AS 数据源 PIVOT ( -- 对目标字段取聚合值(因为同一个UniqueID+状态只会有一条,MAX/Min都可以) MAX(目标字段) -- 指定要转成列的字段是状态字段,列名是'in'和'out' FOR 状态字段 IN ([in], [out]) ) AS 透视结果表
方案3:用DISTINCT临时去重(谨慎使用)
如果'in'和'out'对应的其他所有字段完全一致,只是状态字段不同,且你不在乎最终保留哪个状态,那可以在SELECT后面加DISTINCT来过滤重复行:
SELECT DISTINCT 主表.UniqueID, 主表.字段A, 主表.字段B, s.状态字段, s.目标字段 FROM 主表 JOIN 你的状态表 s ON 主表.UniqueID = s.UniqueID
不过这个方法要谨慎,因为它会过滤掉所有完全重复的行,万一你的数据里还有其他非状态导致的重复,可能会误删有用的数据,所以优先推荐前两种方案。
内容的提问来源于stack exchange,提问作者Just_Stacking
相关产品推荐
相关产品推荐

