如何在 Microsoft SQL Server Management Studio 中将多行合并为一行,用逗号分隔

Posted

技术标签:

【中文标题】如何在 Microsoft SQL Server Management Studio 中将多行合并为一行,用逗号分隔【英文标题】:How do you merge multiple rows into a single row in Microsoft SQL Server Management Studio, separate by comma 【发布时间】:2021-06-08 14:11:38 【问题描述】:

我正在尝试根据匹配的 user_id 将以下 ID 连接到一行中。

当前代码

SELECT
A.USER_ID,
B.POINT_ID

FROM DATABASE1 AS A
LEFT JOIN DATABASE2 as b on a.SSCL_ID = b.SEC_ID

WHERE
RECORD_STATUS in ('2','5')
and USER_STATUS = '1'

我尝试了以下代码:

SELECT c.USER_ID,
    STUFF((SELECT DISTINCT ',' + cast(POINT_ID as varchar(10))
            FROM DATABASE1 A
            LEFT JOIN DATABASE2 as b on a.SSCL_ID = b.SEC_ID
            FOR XML PATH ('')), 1, 1, '') 
    from DATABASE1 c
      WHERE
       RECORD_STATUS in ('2','5')
       and USER_STATUS = '1'
    group by c.USER_ID

【问题讨论】:

您在子查询中缺少 WHERE 的隐式 JOIN 不确定我是否理解您的评论。我在 a.SSCL_ID = b.SEC_ID 上有 LEFT JOIN DATABASE2 作为 b。有什么需要补充的吗? 那么cab有什么关系呢?这是您查询中的交叉连接。 c 与子查询中的每一行 行相关(由来自ab 的数据组成)。 在提出问题时,您需要提供一个可重现的最小示例。请参考以下链接:***.com/help/minimal-reproducible-example 请提供以下内容: (1) DDL 和样本数据填充,即 CREATE table(s) 加上 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试在 T-SQL 中实现它。 (3) 期望的输出,基于上面#1 中的样本数据。 (4) 你的 SQL Server 版本 (SELECT @@version;) 【参考方案1】:

请尝试以下解决方案。

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, [USER_ID] VARCHAR(10), POINT_ID INT);
INSERT INTO @tbl ([USER_ID], POINT_ID) VALUES
('T0070',1 ),
('T0070',2 ),
('T0070',3 ),
('T1234',10),
('T1234',11),
('T1234',12),
('T1234',13),
('T1234',14);
-- DDL and sample data population, end

DECLARE @separator CHAR(1) = ',';

SELECT p.[USER_ID], 
   STUFF((SELECT @separator + CAST(POINT_ID AS VARCHAR(30)) AS [text()]
      FROM @tbl AS c
      WHERE c.[USER_ID] = p.[USER_ID] 
      ORDER BY c.POINT_ID
      FOR XML PATH(''), TYPE).value('text()[1]','NVARCHAR(MAX)'), 1, 1, NULL) AS POINT_ID_LIST
FROM @tbl AS p
GROUP BY p.USER_ID;

输出

+---------+----------------+
| USER_ID | POINT_ID_LIST  |
+---------+----------------+
| T0070   |          1,2,3 |
| T1234   | 10,11,12,13,14 |
+---------+----------------+

【讨论】:

@Charlieface,谢谢,考虑到了。 OP安静了很久。【参考方案2】:

内部FOR XML PATH聚合必须是外部USER_ID的函数

with cte as(
    SELECT
      A.USER_ID,
      B.POINT_ID
    FROM DATABASE1 AS A
    LEFT JOIN DATABASE2 as b on a.SSCL_ID = b.SEC_ID
    WHERE
      RECORD_STATUS in ('2','5')
      and USER_STATUS = '1'
)
SELECT c1.USER_ID,
    STUFF((SELECT ',' + cast(POINT_ID as varchar(10))
            FROM cte c2
            WHERE c2.USER_ID = c1.USER_ID
            FOR XML PATH ('')), 1, 1, '')
FROM cte c1

【讨论】:

FOR XML PATH (''), TYPE).value('text()[1]','nvarchar(max)'), 1, 1, '') 防止 XML 实体化【参考方案3】:

你能用string_agg()吗?

SELECT A.USER_ID, STRING_AGG(B.POINT_ID, ',')
FROM DATABASE1 A LEFT JOIN
     DATABASE2 b 
     ON a.SSCL_ID = b.SEC_ID
WHERE RECORD_STATUS in ('2', '5') AND
      USER_STATUS = '1'
GROUP BY A.USER_ID;

【讨论】:

嗨,戈登。刚刚尝试过,它给了我错误“'STRING_AGG' 不是可识别的内置函数名称。” @Meowzz 你需要 SQL Server 2017+

以上是关于如何在 Microsoft SQL Server Management Studio 中将多行合并为一行,用逗号分隔的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Microsoft SQL Server 2017 上调试存储过程?

如何在 Microsoft PowerBI 中使用 SQL Server 存储过程?

如何在 Microsoft SQL Server Management Studio 2014 中更新表

如何将 sql server 链接到 Microsoft Access?

如何在 Microsoft SQL Server 中制作非数值表的数据透视表?

收藏Windows 如何安装Microsoft SQL Server 2000