考虑一个包含名称的数据库表,其中有三行:

Peter
Paul
Mary

有没有一种简单的方法可以把它变成彼得、保罗、玛丽的一串?


当前回答

提出了递归CTE解决方案,但没有提供代码。下面的代码是递归CTE的示例。

请注意,虽然结果与问题相符,但数据与给定的描述并不完全相符,因为我假设您确实希望对行组(而不是表中的所有行)执行此操作。将其更改为与表中的所有行相匹配是读者的练习。

;WITH basetable AS (
    SELECT
        id,
        CAST(name AS VARCHAR(MAX)) name,
        ROW_NUMBER() OVER (Partition BY id ORDER BY seq) rw,
        COUNT(*) OVER (Partition BY id) recs
    FROM (VALUES
        (1, 'Johnny', 1),
        (1, 'M', 2),
        (2, 'Bill', 1),
        (2, 'S.', 4),
        (2, 'Preston', 5),
        (2, 'Esq.', 6),
        (3, 'Ted', 1),
        (3, 'Theodore', 2),
        (3, 'Logan', 3),
        (4, 'Peter', 1),
        (4, 'Paul', 2),
        (4, 'Mary', 3)
    ) g (id, name, seq)
),
rCTE AS (
    SELECT recs, id, name, rw
    FROM basetable
    WHERE rw = 1

    UNION ALL

    SELECT b.recs, r.ID, r.name +', '+ b.name name, r.rw + 1
    FROM basetable b
    INNER JOIN rCTE r ON b.id = r.id AND b.rw = r.rw + 1
)
SELECT name
FROM rCTE
WHERE recs = rw AND ID=4
OPTION (MAXRECURSION 101)

其他回答

要避免空值,可以使用CONCAT()

DECLARE @names VARCHAR(500)
SELECT @names = CONCAT(@names, ' ', name) 
FROM Names
select @names

SQL Server中尚未通过XML data()命令显示的一个方法是:

假设一个名为NameList的表有一列名为FName,

SELECT FName + ', ' AS 'data()'
FROM NameList
FOR XML PATH('')

返回:

"Peter, Paul, Mary, "

只需处理额外的逗号。

正如@NReilingh的注释所采用的,您可以使用以下方法删除尾随逗号。假设表和列名相同:

STUFF(REPLACE((SELECT '#!' + LTRIM(RTRIM(FName)) AS 'data()' FROM NameList
FOR XML PATH('')),' #!',', '), 1, 2, '') as Brands

我在家里无法访问SQL Server,所以我猜测这里的语法,但大致上是这样的:

DECLARE @names VARCHAR(500)

SELECT @names = @names + ' ' + Name
FROM Names

此答案需要服务器上的某些权限才能工作。

装配是一个很好的选择。有很多网站解释如何创建它。我认为解释得很好的就是这个。

如果您愿意,我已经创建了程序集,可以在这里下载DLL文件。

下载后,需要在SQL Server中运行以下脚本:

EXEC sp_configure 'show advanced options', 1
RECONFIGURE;
EXEC sp_configure 'clr strict security', 1;
RECONFIGURE;

CREATE Assembly concat_assembly
   AUTHORIZATION dbo
   FROM '<PATH TO Concat.dll IN SERVER>'
   WITH PERMISSION_SET = SAFE;
GO

CREATE AGGREGATE dbo.concat (

    @Value NVARCHAR(MAX)
  , @Delimiter NVARCHAR(4000)

) RETURNS NVARCHAR(MAX)
EXTERNAL Name concat_assembly.[Concat.Concat];
GO

sp_configure 'clr enabled', 1;
RECONFIGURE

请注意,服务器可以访问程序集的路径。由于您已成功完成所有步骤,因此可以使用以下功能:

SELECT dbo.Concat(field1, ',')
FROM Table1

自SQL Server 2017以来,可以使用STRING_AGG函数。

使用XML帮助我用逗号分隔行。对于额外的逗号,我们可以使用SQL Server的replace函数。使用AS“data()”将用空格连接行,而不是添加逗号,稍后可以用逗号替换,语法如下所示。

REPLACE(
        (select FName AS 'data()'  from NameList  for xml path(''))
         , ' ', ', ')