如何在 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。有什么需要补充的吗?
那么c
与a
和b
有什么关系呢?这是您查询中的交叉连接。 c
与子查询中的每一行 行相关(由来自a
和b
的数据组成)。
在提出问题时,您需要提供一个可重现的最小示例。请参考以下链接:***.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?