99

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

用户名
--------
保罗
约翰
玛丽

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

保罗、约翰、玛丽

我该怎么做呢?

4

10 回答 10

133
 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

之前有错字,上面的作品

于 2009-11-23T21:00:06.630 回答
111

这应该适合你。一直测试到 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))
于 2009-05-20T12:44:50.727 回答
57

对几种方法的良好审查:

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

文章副本 -

Coalesce 不是 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

这个查询可能相当有效,但需要注意,并且应该正确理解 COALESCE 的使用。COALESCE 是 ISNULL 的版本,它可以接受两个以上的参数。它返回参数列表中不为空的第一件事。所以实际上它与连接无关,下面的代码是完全相同的——不使用 COALESCE:

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

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

SELECT @categories

但是数据库的无序特性使得这不可靠。T-SQL(还)没有连接函数的全部原因是,这是一个聚合,元素的顺序很重要。使用这种字符串连接的变量赋值方法,您实际上可能会发现返回的答案中没有所有值,特别是如果您希望将子字符串按特定顺序放置。考虑以下内容,当我希望它返回 ',Bikes,Clothing,Components,Accessories' 时,它在我的机器上只返回 ',Accessories':

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

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

SELECT @categories

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

SELECT ',' + Name
FROM Production.ProductCategory
ORDER BY LEN(Name)
FOR XML PATH('') 

在我最近比较使用子查询时的 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
; 

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

于 2009-05-20T16:06:29.697 回答
12

基于 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
于 2015-07-17T14:56:40.943 回答
8

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

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

于 2011-11-04T11:54:28.687 回答
7
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

于 2011-01-12T18:50:03.150 回答
6

在 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;
于 2012-02-13T07:41:19.740 回答
4

您可以使用 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;

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

于 2014-05-30T10:44:41.290 回答
3

MS SQL Server 2005/2008 中一个简洁灵活的解决方案是创建一个 CLR Agregate 函数。

你会在google上找到很多文章(带有代码)。

看起来这篇文章将引导您使用 C# 完成整个过程。

于 2009-05-20T19:15:54.900 回答
-5

如果你是通过 PHP 来执行的,那么这个呢?

$hQuery = mysql_query("SELECT * FROM users");
while($hRow = mysql_fetch_array($hQuery)) {
    $hOut .= $hRow['username'] . ", ";
}
$hOut = substr($hOut, 0, strlen($hOut) - 1);
echo $hOut;
于 2009-05-20T12:49:24.120 回答