Convert multiple rows into one with comma as separator
如果我发布
1 2 3 4 5 | username -------- Paul John Mary |
但我真正需要的是一行,所有值都用逗号分隔,如下所示:
1 | Paul, John, Mary |
我该怎么做?
1 2 3 4 5 6 7 8 9 10 11 | 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 |
以前有打字错误,上面的工作
这应该对你有用。一直测试到SQL 2000。
1 2 3 4 5 6 7 8 9 10 11 | 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)) |
很好地回顾了几种方法:
http://blogs.msmvps.com/robfarley/2007/04/07/coalesce-is-not-the-answer-to-string-concatation-in-t-sql/
文章拷贝-
Coalesce并不是T-SQL中字符串连接的答案。多年来,我看到过很多关于使用Coalesce函数在T-SQL中实现字符串连接的文章。这是这里的一个例子(从readifarian marc ridey借来)。
1 2 3 4 5 6 7 | DECLARE @categories varchar(200) SET @categories = NULL SELECT @categories = COALESCE(@categories + ',','') + Name FROM Production.ProductCategory SELECT @categories |
这个查询可能非常有效,但是需要小心,并且应该正确理解联合的使用。Coalesce是isNull的版本,它可以接受两个以上的参数。它返回参数列表中不为空的第一项。所以实际上,它与串联没有任何关系,下面的代码是完全相同的——不使用coalesce:
1 2 3 4 5 6 7 | DECLARE @categories varchar(200) SET @categories = '' SELECT @categories = @categories + ',' + Name FROM Production.ProductCategory SELECT @categories |
但是数据库的无序性使得这不可靠。T-SQL没有(还没有)连接函数的全部原因是,这是一个元素顺序很重要的聚合。使用这个字符串串联的变量分配方法,您可能会发现返回的答案中没有所有的值,特别是如果您希望子字符串按特定的顺序排列的话。考虑以下几点,我的机器上只有"附件"在我想要它返回时才返回,自行车、衣服、部件、附件:
1 2 3 4 5 6 7 8 | DECLARE @categories varchar(200) SET @categories = NULL SELECT @categories = COALESCE(@categories + ',','') + Name FROM Production.ProductCategory ORDER BY LEN(Name) SELECT @categories |
更好的方法是使用一种方法,该方法确实考虑了顺序,并且已经包含在sql2005中,专门用于字符串串联-用于XML路径("")
1 2 3 4 | SELECT ',' + Name FROM Production.ProductCategory ORDER BY LEN(Name) FOR XML PATH('') |
在我最近在使用子查询比较group by和distinct的文章中,我演示了for xml路径("")的用法。看看这个,你会发现它在子查询中是如何工作的。"stuff"函数只用于删除前导逗号。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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 ; |
FORXML路径是子查询中唯一可以使用ORDERBY的情况之一。另一个是顶部。当您使用一个未命名的列和XML路径("")时,您将得到一个没有XML标记的直接连接。这确实意味着字符串将被HTML编码,因此,如果您要连接可能包含<字符(etc)的字符串,那么您可以在以后修复它,但无论如何,这仍然是SQL Server 2005中连接字符串的最佳方法。
基于Mwigdahls的答案。如果你还需要做分组,这里是如何让它看起来像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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 |
您可以使用此查询执行上述任务:
1 2 3 | DECLARE @test NVARCHAR(max) SELECT @test = COALESCE(@test + ',', '') + field2 FROM #test SELECT field2 = @test |
有关详细信息和逐步说明,请访问以下链接http://oops-solution.blogspot.com/2011/11/sql-server-convert-table-column-data.html
1 2 3 4 5 6 7 8 | DECLARE @EmployeeList varchar(100) SELECT @EmployeeList = COALESCE(@EmployeeList + ', ', '') + CAST(Emp_UniqueID AS varchar(5)) FROM SalesCallsEmployees WHERE SalCal_UniqueID = 1 SELECT @EmployeeList |
来源:http://www.sqlteam.com/article/using-coalesce-to-build-comma-delimited-string
在sqlite中,这更简单。我认为mysql、mssql和orable有类似的实现
1 2 3 4 5 6 | 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; |
在MS SQL Server 2005/2008中,一个干净而灵活的解决方案是创建一个clr agregate函数。
你会在谷歌上找到很多文章(带代码)。
看起来这篇文章使用C引导您完成整个过程。
可以使用stuff()将行转换为逗号分隔的值
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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; |
感谢@alexkuznetsov提供此答案的参考。
如果您是通过php来执行这个操作,那么这个呢?
1 2 3 4 5 6 | $hQuery = mysql_query("SELECT * FROM users"); while($hRow = mysql_fetch_array($hQuery)) { $hOut .= $hRow['username'] .","; } $hOut = substr($hOut, 0, strlen($hOut) - 1); echo $hOut; |