我正在尝试将一个基于mysql的应用程序迁移到Microsoft SQL Server 2005(不是自愿的,但这就是生活)。

在最初的应用程序中,我们几乎使用了完全符合ANSI-SQL的语句,只有一个重要的例外——我们相当频繁地使用MySQL的group_concat函数。

顺便说一下,Group_concat是这样做的:给定一个表,比如员工姓名和项目……

SELECT empName, projID FROM project_members;

返回:

ANDY   |  A100
ANDY   |  B391
ANDY   |  X010
TOM    |  A100
TOM    |  A510

... 下面是使用group_concat得到的结果:

SELECT 
    empName, group_concat(projID SEPARATOR ' / ') 
FROM 
    project_members 
GROUP BY 
    empName;

返回:

ANDY   |  A100 / B391 / X010
TOM    |  A100 / A510

所以我想知道的是:是否有可能写,说,一个用户定义的函数在SQL Server模拟group_concat的功能?

我几乎没有使用udf,存储过程或类似的东西的经验,只是直接的SQL,所以请在解释太多的一边犯错:)


当前回答

对于我的谷歌同事们,这里有一个非常简单的即插即用的解决方案,在我与更复杂的解决方案斗争了一段时间后,它为我工作:

SELECT
distinct empName,
NewColumnName=STUFF((SELECT ','+ CONVERT(VARCHAR(10), projID ) 
                     FROM returns 
                     WHERE empName=t.empName FOR XML PATH('')) , 1 , 1 , '' )
FROM 
returns t

注意,我必须将ID转换为VARCHAR,以便将其作为字符串连接起来。如果你不需要这样做,这里有一个更简单的版本:

SELECT
distinct empName,
NewColumnName=STUFF((SELECT ','+ projID
                     FROM returns 
                     WHERE empName=t.empName FOR XML PATH('')) , 1 , 1 , '' )
FROM 
returns t

所有的功劳都归于这里: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/9508abc2-46e7-4186-b57f-7f368374e084/replicating-groupconcat-function-of-mysql-in-sql-server?forum=transactsql

其他回答

看看Github上的GROUP_CONCAT项目,我认为我做的正是你正在搜索的:

该项目包含一组SQLCLR用户定义聚合函数(SQLCLR UDAs),它们共同提供与MySQL GROUP_CONCAT函数类似的功能。有多种功能,以确保基于所需功能的最佳性能…

尝试了这些方法,但对于我在MS SQL Server 2005中使用的目的来说,以下是最有用的,我在xaprb找到的

declare @result varchar(8000);

set @result = '';

select @result = @result + name + ' '

from master.dbo.systypes;

select rtrim(@result);

@Mark,正如你提到的,空格字符给我带来了问题。

2021

@AbdusSalamAzad的答案是正确的。

SELECT STRING_AGG(my_col, ',') AS my_result FROM my_tbl;

如果结果太大,可能会出现“STRING_AGG aggregation result exceeded the limit of 8000 bytes”错误。使用LOB类型来避免结果截断。”,可以通过更改查询来修复:

SELECT STRING_AGG(convert(varchar(max), my_col), ',') AS my_result FROM my_tbl;

我可能有点晚了,但这个方法对我来说是有效的,比COALESCE方法更容易。

SELECT STUFF(
             (SELECT ',' + Column_Name 
              FROM Table_Name
              FOR XML PATH (''))
             , 1, 1, '')

关于J Hardiman的回答,怎么样:

SELECT empName, projIDs=
  REPLACE(
    REPLACE(
      (SELECT REPLACE(projID, ' ', '-somebody-puts-microsoft-out-of-his-misery-please-') AS [data()] FROM project_members WHERE empName=a.empName FOR XML PATH('')), 
      ' ', 
      ' / '), 
    '-somebody-puts-microsoft-out-of-his-misery-please-',
    ' ') 
  FROM project_members a WHERE empName IS NOT NULL GROUP BY empName

顺便问一下,“姓氏”的使用是一个拼写错误还是我没有理解一个概念?

无论如何,非常感谢大家,因为这节省了我很多时间:)