使用逗号作为分隔符将多行转换为一行

Pav*_*tov 71 t-sql csv rows

如果我发出SELECT username FROM Users我得到这个结果:

username
--------
Paul
John
Mary

但我真正需要的是一个行与所有以逗号分隔值,如下所示:

Paul, John, Mary

我该怎么做呢?

Hog*_*gan 108

 select
   distinct  
    stuff((
        select ',' + u.username
        from users u
        where u.username = username
        order by u.username
        for xml path('')
    ),1,1,'') as userlist
from users
group by username
Run Code Online (Sandbox Code Playgroud)

之前有一个错字,上面的作品

  • @BoratSagdiyev - kehrk错了,`FOR XML`自动编码,请参阅http://sqlfiddle.com/#!6/b824a/1 (6认同)
  • 免责声明:对于具有特殊字符(如"<"或"&")的数据,此**不起作用. (4认同)
  • @kehrk - 嗯......不.工作良好.http://sqlfiddle.com/#!6/b824a/1 (4认同)
  • 你是个天才.此外,这会在列表前面放置一个空格.使STUFF选项1,2,它将删除该空间.我现在需要弄清楚这是怎么回事. (2认同)
  • 应该是公认的答案 (2认同)

mwi*_*ahl 88

这应该适合你.一直测试回到SQL 2000.

create table #user (username varchar(25))

insert into #user (username) values ('Paul')
insert into #user (username) values ('John')
insert into #user (username) values ('Mary')

declare @tmp varchar(250)
SET @tmp = ''
select @tmp = @tmp + username + ', ' from #user

select SUBSTRING(@tmp, 0, LEN(@tmp))
Run Code Online (Sandbox Code Playgroud)

  • SQL Server 2017/SQL Azure支持STRING_AGG - https://docs.microsoft.com/en-us/sql/t-sql/functions/string-agg-transact-sql https://stackoverflow.com/a /一百五十四万五千五百六十九分之四千二百七十七万八千零五十零 (4认同)

A-K*_*A-K 44

对几种方法的好评:

http://blogs.msmvps.com/robfarley/2007/04/07/coalesce-is-not-the-answer-to-string-concatentation-in-t-sql/

文章副本 -

合并是没有答案在T-SQL字符串连接我见过多年来许多职位有关使用COALESCE函数来得到字符串连接在T-SQL的工作.这是这里的一个例子(借用了Readifarian Marc Ridey).

DECLARE @categories varchar(200)
SET @categories = NULL

SELECT @categories = COALESCE(@categories + ',','') + Name
FROM Production.ProductCategory

SELECT @categories
Run Code Online (Sandbox Code Playgroud)

此查询可能非常有效,但需要注意,并且应正确理解COALESCE的使用.COALESCE是ISNULL的版本,可以使用两个以上的参数.它返回参数列表中的第一个不为null的东西.所以它实际上与连接无关,而下面的代码完全相同 - 不使用COALESCE:

DECLARE @categories varchar(200)
SET @categories = ''

SELECT @categories = @categories + ',' + Name
FROM Production.ProductCategory

SELECT @categories
Run Code Online (Sandbox Code Playgroud)

但是数据库的无序性使得这种不可靠.T-SQL没有(还)具有连接函数的全部原因是,这是一个元素顺序很重要的聚合.使用字符串连接的这个变量赋值方法,你实际上可能发现,被返回的答案不具有的所有值它,特别是如果你想放在一个特定的顺序子.考虑以下情况,在我的机器上只返回',附件',当我希望它返回',自行车,服装,组件,配件'时:

DECLARE @categories varchar(200)
SET @categories = NULL

SELECT @categories = COALESCE(@categories + ',','') + Name
FROM Production.ProductCategory
ORDER BY LEN(Name)

SELECT @categories
Run Code Online (Sandbox Code Playgroud)

更好的方法是使用一个考虑到顺序的方法,并且已经包含在SQL2005中专门用于字符串连接的目的 - FOR XML PATH('')

SELECT ',' + Name
FROM Production.ProductCategory
ORDER BY LEN(Name)
FOR XML PATH('') 
Run Code Online (Sandbox Code Playgroud)

在我最近使用子查询比较GROUP BY和DISTINCT的帖子中,我演示了使用FOR XML PATH('').看看这个,你会看到它在子查询中是如何工作的.'STUFF'功能仅用于删除前导逗号.

USE tempdb;
GO
CREATE TABLE t1 (id INT, NAME VARCHAR(MAX));
INSERT t1 values (1,'Jamie');
INSERT t1 values (1,'Joe');
INSERT t1 values (1,'John');
INSERT t1 values (2,'Sai');
INSERT t1 values (2,'Sam');
GO

select
    id,
    stuff((
        select ',' + t.[name]
        from t1 t
        where t.id = t1.id
        order by t.[name]
        for xml path('')
    ),1,1,'') as name_csv
from t1
group by id
; 
Run Code Online (Sandbox Code Playgroud)

FOR XML PATH是您可以在子查询中使用ORDER BY的唯一情况之一.另一个是TOP.当您使用未命名的列和FOR XML PATH('')时,您将获得直接连接,没有XML标记.这确实意味着字符串将是HTML编码的,所以如果你连接可能有<字符(等)的字符串,那么你应该在之后修复它,但不管怎样,这仍然是连接字符串的最佳方式在SQL Server 2005中.

  • @AlexKuznetsov - 仅供参考 - 这篇文章已有 7 年的历史,其中包含自 SQL 2008 发布以来就已不真实的信息。 (2认同)

Tom*_*ald 10

建立在mwigdahls的答案.如果你还需要在这里进行分组是如何让它看起来像

group, csv
'group1', 'paul, john'
'group2', 'mary'

    --drop table #user
create table #user (groupName varchar(25), username varchar(25))

insert into #user (groupname, username) values ('apostles', 'Paul')
insert into #user (groupname, username) values ('apostles', 'John')
insert into #user (groupname, username) values ('family','Mary')


select
    g1.groupname
    , stuff((
        select ', ' + g.username
        from #user g        
        where g.groupName = g1.groupname        
        order by g.username
        for xml path('')
    ),1,2,'') as name_csv
from #user g1
group by g1.groupname
Run Code Online (Sandbox Code Playgroud)


小智 6

DECLARE @EmployeeList varchar(100)

SELECT @EmployeeList = COALESCE(@EmployeeList + ', ', '') + 
   CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1

SELECT @EmployeeList
Run Code Online (Sandbox Code Playgroud)

来源:http: //www.sqlteam.com/article/using-coalesce-to-build-comma-delimited-string


小智 6

您可以使用此查询执行上述任务:

DECLARE @test NVARCHAR(max)  
SELECT @test = COALESCE(@test + ',', '') + field2 FROM #test
SELECT field2 = @test 
Run Code Online (Sandbox Code Playgroud)

有关详细信息和分步说明,请访问以下链接 http://oops-solution.blogspot.com/2011/11/sql-server-convert-table-column-data.html


elc*_*uco 5

在SQLite中,这更简单。我认为对于MySQL,MSSql和Orable也有类似的实现

CREATE TABLE Beatles (id integer, name string );
INSERT INTO Beatles VALUES (1, "Paul");
INSERT INTO Beatles VALUES (2, "John");
INSERT INTO Beatles VALUES (3, "Ringo");
INSERT INTO Beatles VALUES (4, "George");
SELECT GROUP_CONCAT(name, ',') FROM Beatles;
Run Code Online (Sandbox Code Playgroud)


Ram*_*Ram 5

您可以使用 stuff() 将行转换为逗号分隔值

select
EmployeeID,
stuff((
  SELECT ',' + FPProjectMaster.GroupName 
      FROM     FPProjectInfo AS t INNER JOIN
              FPProjectMaster ON t.ProjectID = FPProjectMaster.ProjectID
      WHERE  (t.EmployeeID = FPProjectInfo.EmployeeID)
              And t.STatusID = 1
              ORDER BY t.ProjectID
       for xml path('')
       ),1,1,'') as name_csv
from FPProjectInfo
group by EmployeeID;
Run Code Online (Sandbox Code Playgroud)

感谢@AlexKuznetsov 提供参考以获得此答案。