基于条件的SQL Server Stuff函数使用:按ImageID分组去重拼接字段
实现SQL Server按ImageID分组去重拼接Brand和Segment
没问题,我来帮你搞定这个需求!要实现按ImageID分组,将同一组内不重复的Brand和Segment组合拼接起来,我们可以结合DISTINCT和STUFF函数来实现,要是你的SQL Server版本是2017及以上,还有更简洁的方案。
先准备示例测试数据
首先我们创建一张测试表并插入数据,模拟你提到的重复场景:
CREATE TABLE ImageDetails ( ImageID INT, Brand VARCHAR(50), Segment VARCHAR(50) ); INSERT INTO ImageDetails VALUES (101, 'Nescafe', 'Coffee'), (101, 'Nescafe', 'Coffee'), -- 完全重复的记录 (101, 'NESCAFE', 'Coffee'), -- 大小写不同的Brand (102, 'Kitkat', 'Chocolate'), (102, 'Kitkat', 'Chocolate'), (102, 'Cadbury', 'Chocolate'), (103, 'Lays', 'Snacks');
方法一:使用STUFF + FOR XML PATH(兼容所有SQL Server版本)
核心思路是先对每个ImageID下的Brand+Segment组合做去重,再用STUFF拼接结果:
-- 第一步:先提取每个ImageID下不重复的Brand-Segment组合 WITH DistinctImageData AS ( SELECT DISTINCT ImageID, Brand + ' - ' + Segment AS BrandSegment -- 将Brand和Segment合并为单个字符串,方便去重和拼接 FROM ImageDetails ) -- 第二步:按ImageID分组拼接 SELECT ImageID, STUFF( -- 用FOR XML PATH将多行转为单个字符串 (SELECT ', ' + BrandSegment FROM DistinctImageData d WHERE d.ImageID = main.ImageID FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '' -- 去掉字符串开头多余的", " ) AS CombinedBrandSegments FROM DistinctImageData main GROUP BY ImageID;
执行后,ImageID=101会得到Nescafe - Coffee, NESCAFE - Coffee(如果需要忽略大小写去重,后面会讲处理方式),ImageID=102会得到Kitkat - Chocolate, Cadbury - Chocolate,完全符合你的需求。
方法二:使用STRING_AGG(SQL Server 2017+ 推荐)
如果你的SQL Server版本是2017或更高,STRING_AGG函数直接支持DISTINCT关键字,写法更简洁:
SELECT ImageID, STRING_AGG(DISTINCT Brand + ' - ' + Segment, ', ') AS CombinedBrandSegments FROM ImageDetails GROUP BY ImageID;
这个方法和上面的效果完全一致,但代码更短,维护起来更方便。
额外需求:忽略大小写去重
如果需要把Nescafe和NESCAFE视为同一个Brand,可以先统一转为小写(或大写)再去重:
WITH NormalizedData AS ( SELECT ImageID, Brand, Segment, -- 生成标准化的去重键 LOWER(Brand) + '|' + LOWER(Segment) AS NormalizedKey FROM ImageDetails ), UniqueCombined AS ( -- 按标准化键去重,保留原始的Brand和Segment SELECT ImageID, MIN(Brand) AS Brand, -- 取同一标准化组下的任意一个原始Brand(MIN/MAX都可以) MIN(Segment) AS Segment FROM NormalizedData GROUP BY ImageID, NormalizedKey ) -- 最后拼接结果 SELECT ImageID, STUFF( (SELECT ', ' + Brand + ' - ' + Segment FROM UniqueCombined u WHERE u.ImageID = main.ImageID FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '' ) AS CombinedBrandSegments FROM UniqueCombined main GROUP BY ImageID;
执行后,ImageID=101只会得到Nescafe - Coffee,大小写不同的重复项会被合并。
内容的提问来源于stack exchange,提问作者MDMalik
相关产品推荐
相关产品推荐

