You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server 2016:多列分组合并指定列值技术求助

问题:按5列分组合并第6列多行值(SQL Server 2016)

我有一批数据,其中5列内容完全相同,仅第6列存在差异。希望按这5列进行分组,将第6列的多行值合并为一行。尝试过CTE和STUFF函数但未达预期,多数示例仅处理两列场景;使用SQL Server 2016(版本130),无法使用STRING_AGG函数。

当前查询返回的数据

站点名称页面标题页面URL创建日期过期日期审核人
xSitesql concat//abc.com/fr02/02/202328/02/2023James (jk jk@something.com)
xSitesql concat//abc.com/fr02/02/202328/02/2023David (dDel jk@something.com)
xSitesql concat//abc.com/fr02/02/202328/02/2023Ali (aLee aLee@something.com)
xSiteJoin in SQL//abc.com/vf18/02/20202/05/2022Ken (kK kk@something.com)
ySiteJust SQL//abc.com/a31/01/202221/05/2023

期望返回的结果

站点名称页面标题页面URL创建日期过期日期审核人
xSitesql concat//abc.com/fr02/02/202328/02/2023James (jk jk@something.com), David (dDel jk@something.com), Ali (aLee aLee@something.com)
xSiteJoin in SQL//abc.com/vf18/02/20202/05/2022Ken (kK kk@something.com)
ySiteJust SQL//abc.com/a31/01/202221/05/2023

我尝试的SQL代码

WITH cte_contentExpiry AS (        

    SELECT c.sitename
          ,c.pagetitle
          ,c.pageurl
          ,c.dateCreated
          ,c.expiryDate
          ,a.userid
    FROM dbo.content c
    LEFT OUTER JOIN dbo.assignments a
                 ON c.contentId     = a.contentId
    WHERE c.active   = 1

) SELECT   q.sitename
          ,q.pagetitle
          ,q.pageurl
          ,q.dateCreated
          ,q.expiryDate
        ,
        STUFF((SELECT '; ' + u.fName +  ' (' + u.userName + ' - ' + u.email + ')'
            FROM dbo.users u
            WHERE q.userId        = u.userId
            FOR XML PATH('')), 1, 1, '')  AS reviewer
    FROM cte_contentExpiry q
GROUP BY   q.sitename
          ,q.pagetitle
          ,q.pageurl
          ,q.dateCreated
          ,q.expiryDate
          ,q.userId

解决方案

你的核心问题是分组时包含了userId,导致每个不同的userId都会生成单独一行,无法实现按前5列合并的效果。此外,子查询需要关联的是前5列而非userId,才能将同一组下的所有审核人合并。

修正后的SQL代码如下:

WITH cte_contentExpiry AS (        
    SELECT 
        c.sitename,
        c.pagetitle,
        c.pageurl,
        c.dateCreated,
        c.expiryDate,
        -- 提前拼接好审核人的完整信息
        CONCAT(u.fName, ' (', u.userName, ' ', u.email, ')') AS reviewer_info
    FROM dbo.content c
    LEFT JOIN dbo.assignments a ON c.contentId = a.contentId
    LEFT JOIN dbo.users u ON a.userid = u.userId -- 直接关联用户表获取完整信息
    WHERE c.active = 1
)
SELECT 
    sitename,
    pagetitle,
    pageurl,
    dateCreated,
    expiryDate,
    -- 合并同一组的所有审核人
    STUFF(
        (SELECT ', ' + reviewer_info 
         FROM cte_contentExpiry sub
         WHERE sub.sitename = main.sitename
           AND sub.pagetitle = main.pagetitle
           AND sub.pageurl = main.pageurl
           AND sub.dateCreated = main.dateCreated
           AND sub.expiryDate = main.expiryDate
         FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),
        1, 2, '' -- 移除开头多余的', '
    ) AS 审核人
FROM cte_contentExpiry main
GROUP BY sitename, pagetitle, pageurl, dateCreated, expiryDate;

关键修正说明:

  1. 移除分组中的userId,仅按需要合并的5列分组
  2. 子查询通过关联前5列,确保同一组的所有审核人都被纳入合并范围
  3. 使用TYPE和.value('.', 'NVARCHAR(MAX)')避免特殊字符被转义(如<、>等)
  4. 在CTE中提前拼接审核人信息,简化子查询逻辑

如果需要处理审核人为空的场景(如ySite的数据),可以用ISNULL将结果转为空字符串:

ISNULL(
    STUFF(
        (SELECT ', ' + reviewer_info 
         FROM cte_contentExpiry sub
         WHERE sub.sitename = main.sitename
           AND sub.pagetitle = main.pagetitle
           AND sub.pageurl = main.pageurl
           AND sub.dateCreated = main.dateCreated
           AND sub.expiryDate = main.expiryDate
         FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),
        1, 2, ''
    ), ''
) AS 审核人

内容的提问来源于stack exchange,提问作者david-l

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 14:27:24