基于另一个列值合并列值 - SQL

Posted

技术标签:

【中文标题】基于另一个列值合并列值 - SQL【英文标题】:Merge column value based on another column value - TSQL 【发布时间】:2021-12-02 15:58:48 【问题描述】:

我正在使用以下查询根据表 Customers 中的列“Customer_Name”合并列 Message

SELECT
  [Customer_Name],
  STUFF((SELECT
    ', ' + LTRIM(RTRIM([Message]))
  FROM [dbo].[Customers] t2
  WHERE t2.[Customer_Name] = t1.[Customer_Name]
  FOR XML PATH ('')), 1, 1, '')
FROM [dbo].[Customers] t1
GROUP BY [Customer_Name]

使用上面的代码,Message, 分隔,但我想要一个新行。我尝试使用CHAR(13)+CHAR(10),但我得到#x0D;,合并列似乎是错误的。

任何关于如何解决它的想法将不胜感激。

使用 @Larnu 帮助和 cmets 上的帖子回答

SELECT
  [Customer_Name],
  STUFF((SELECT
    (CHAR(13) + CHAR(10)) + LTRIM(RTRIM([Message]))
  FROM [Customers] t2
  WHERE t2.[Customer_Name] = t1.[Customer_Name]
  FOR XML PATH (''),TYPE
    ).value('(./text())[1]','varchar(MAX)'),1,2,'')
FROM [Customers] t1
GROUP BY [Customer_Name]

【问题讨论】:

这能回答你的问题吗? String_agg for SQL Server before 2017(特别是我的回答,解释了为什么会发生这种情况以及如何解决它。) @Larnu 我尝试效仿你的例子,但我没有设法用新行替换,。我的代码在, 方面运行良好。请求是用新行替换“,”。您能否提供一些指导方针? 如果你想要一个新行然后使用CHAR(13)+CHAR(10),而不是',',这是一个回车后跟一个换行符,然后确保你得到了XML的value,比如我在答案中显示。 @Larnu 我尝试修改查询,但现在我在第一个 Message 之前有一个空格,在新消息之前有 2 个空格。有什么建议吗? 如果您的数据中有“空格”。但是您的 CHAR 函数使用了错误的方式,并且您只删除了带有 STUFF 的第一个字符,而不是前 2 个。 【参考方案1】:

您的解决方案使用 xml 序列化。

#x0D;char(13)

的xml序列化

如果您至少使用 SQL Server 2017,则可以使用 STRING_AGG 函数

SELECT
  [Customer_Name],
  STRING_AGG([Message],', ') as [Messages]
FROM [dbo].[Customers] t1
GROUP BY [Customer_Name]

否则您可以添加替换

SELECT
  [Customer_Name],
  REPLACE(
  STUFF((SELECT
    ', ' + LTRIM(RTRIM([Message])) 
  FROM [dbo].[Customers] t2
  WHERE t2.[Customer_Name] = t1.[Customer_Name]
  FOR XML PATH ('')), 1, 2, ''),
  '#x0D;',
  CHAR(13)) as [Messages]
FROM [dbo].[Customers] t1
GROUP BY [Customer_Name]

【讨论】:

【参考方案2】:

防止 XML 实体化的正确方法实际上是使用 TYPE 选项将其生成为 xml 数据类型,然后使用 .value 将其拉回

DECLARE @sep NVARCHAR(10) = ', ';  -- or you can use CHAR(13)+CHAR(10)
SELECT
  [Customer_Name],
  STUFF(
    (SELECT @sep + LTRIM(RTRIM([Message]))
     FROM [dbo].[Customers] t2
     WHERE t2.[Customer_Name] = t1.[Customer_Name]
     FOR XML PATH (''), TYPE
    ).value('text()[1]','nvarchar(max)'), 1, LEN(@sep), '')
FROM [dbo].[Customers] t1
GROUP BY [Customer_Name]

【讨论】:

以上是关于基于另一个列值合并列值 - SQL的主要内容,如果未能解决你的问题,请参考以下文章

比较列值并合并

有难度的sql相同列值合并行

sql把相同条件的列值合并在一起,并用“;”分隔

SQL语句 合并列值 将一列的多个值合并成一行

将两个具有相似列值的数据框合并在一起[重复]

SQL语句:合并列值(将一列的多个值合并成一行)