SQL需求:将唯一姓氏与对应名字合并为指定格式字符串
解决方案
针对你的需求,我们可以通过分组拼接+格式判断的方式实现目标输出,以下提供两种兼容不同SQL Server版本的方案:
方案一:兼容SQL Server 2005及以上版本(基于XML PATH)
-- 按姓氏分组,拼接名字并统计人数 WITH GroupedPeople AS ( SELECT LastName, -- 用+拼接当前姓氏下的所有名字 STUFF( (SELECT ' + ' + FirstName FROM Person p2 WHERE p2.LastName = p1.LastName FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 3, '' -- 移除开头多余的' + ' ) AS FirstNames, COUNT(*) AS NameCount FROM Person p1 GROUP BY LastName ), -- 生成符合格式要求的分组字符串 FormattedGroups AS ( SELECT CASE -- 多名字时显示「姓氏 名字1 + 名字2」 WHEN NameCount > 1 THEN CONCAT(LastName, ' ', FirstNames) -- 单名字时显示「姓氏 名字」;若要实现可选需求(仅显示姓氏),将此行改为 ELSE LastName ELSE CONCAT(LastName, ' ', FirstNames) END AS GroupString FROM GroupedPeople ) -- 拼接所有分组结果为最终字符串 SELECT STUFF( (SELECT ', ' + GroupString FROM FormattedGroups FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '' -- 移除开头多余的', ' ) AS FinalResult
方案二:SQL Server 2017及以上版本(基于STRING_AGG,更简洁)
如果你的数据库版本支持STRING_AGG函数,代码可以大幅简化:
-- 按姓氏分组拼接名字并统计人数 WITH GroupedPeople AS ( SELECT LastName, STRING_AGG(FirstName, ' + ') AS FirstNames, COUNT(*) AS NameCount FROM Person GROUP BY LastName ), -- 生成格式字符串 FormattedGroups AS ( SELECT CASE WHEN NameCount > 1 THEN CONCAT(LastName, ' ', FirstNames) -- 可选需求:单姓氏仅显示姓氏则改为 ELSE LastName ELSE CONCAT(LastName, ' ', FirstNames) END AS GroupString FROM GroupedPeople ) -- 直接拼接所有分组结果 SELECT STRING_AGG(GroupString, ', ') AS FinalResult FROM FormattedGroups
关键说明
- 分组逻辑:先按
LastName分组,确保每个姓氏只处理一次,这是和你之前代码的核心区别(之前是直接拼接所有人员)。 - 格式控制:通过
CASE语句判断当前姓氏下的名字数量,灵活切换显示格式。 - 可选需求实现:如果需要单姓氏时仅显示姓氏,只需修改
CASE中的ELSE分支为ELSE LastName即可,最终输出会变成「Bloggs Joe + Anne, Smith」。
内容的提问来源于stack exchange,提问作者Callan Buchan
相关产品推荐
相关产品推荐

