如何在Stuff函数中处理NULL值并合并同一ID的记录?
解决同一ID出现多行(NULL+有效值)的SQL视图问题
我来帮你搞定这个问题!你的核心困扰是:原视图查询会因为BM_RLOS_DecisionHistoryForm表中同一ref_no存在不同winame的行,导致生成一条带逗号分隔有效值的记录,和一条带NULL的记录。我们来拆解问题并修复代码:
原代码的问题分析
你用了DISTINCT但依然出现重复行,原因在于外层查询是直接从BM_RLOS_DecisionHistoryForm A中选取所有行:
- 当A的行
winame='RCO'时,子查询能匹配到关联的takenby值,生成逗号分隔的结果; - 当A的行
winame!='RCO'时,子查询的A.winame='RCO'条件不满足,STUFF返回NULL; - 这两种情况的
takenby值不同,所以DISTINCT无法合并它们,最终同一ref_no会出现两行。
修复方案1:先获取唯一的ref_no再关联子查询
这种方式更灵活,可选择只保留有RCO记录的ref_no,或保留所有ref_no:
CREATE VIEW BM_RLOS_VW_RCO_AUTH AS SELECT ref_no, -- 过滤掉NULL的takenby,避免生成无效的逗号分隔串 STUFF(( SELECT ', ' + B.takenby FROM BM_RLOS_DecisionHistoryForm B WHERE B.bpm_referenceno = ref_no AND B.winame = 'RCO' AND B.takenby IS NOT NULL FOR XML PATH(''), TYPE ).value('.', 'nvarchar(max)'), 1, 2, '') AS takenby FROM ( -- 先获取所有唯一的ref_no,可根据需求添加WHERE winame='RCO'过滤 SELECT DISTINCT bpm_referenceno AS ref_no FROM BM_RLOS_DecisionHistoryForm ) AS RefNos
修复方案2:外层过滤+GROUP BY合并
如果只需要保留有RCO记录的ref_no,可以直接在外层过滤并分组:
CREATE VIEW BM_RLOS_VW_RCO_AUTH AS SELECT A.bpm_referenceno AS ref_no, STUFF(( SELECT ', ' + B.takenby FROM BM_RLOS_DecisionHistoryForm B WHERE A.bpm_referenceno = B.bpm_referenceno AND B.winame = 'RCO' AND B.takenby IS NOT NULL FOR XML PATH(''), TYPE ).value('.', 'nvarchar(max)'), 1, 2, '') AS takenby FROM BM_RLOS_DecisionHistoryForm A WHERE A.winame = 'RCO' GROUP BY A.bpm_referenceno
关键优化点
- 新增
AND B.takenby IS NOT NULL:避免把NULL值混入逗号分隔串,生成类似, , xxx的无效内容; - 确保每个
ref_no只被处理一次:要么通过子查询获取唯一ref_no,要么通过GROUP BY合并,彻底解决同一ID多行的问题。
内容的提问来源于stack exchange,提问作者Md Kamran Azam
相关产品推荐
相关产品推荐

