Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在MicrosoftSQLServer2005中模拟group_concat MySQL函数?_Sql_Sql Server_Sql Server 2005_String Aggregation - Fatal编程技术网

在MicrosoftSQLServer2005中模拟group_concat MySQL函数?

在MicrosoftSQLServer2005中模拟group_concat MySQL函数?,sql,sql-server,sql-server-2005,string-aggregation,Sql,Sql Server,Sql Server 2005,String Aggregation,我正在尝试将一个基于MySQL的应用程序迁移到MicrosoftSQLServer2005(不是出于选择,但这就是生活) 在最初的应用程序中,我们几乎完全使用了符合ANSI-SQL的语句,但有一个显著的例外——我们相当频繁地使用MySQL的group\u concat函数 顺便说一句,group_concat是这样做的:给定一个员工姓名和项目表 SELECT empName, projID FROM project_members; 返回: ANDY | A100 ANDY | B

我正在尝试将一个基于MySQL的应用程序迁移到MicrosoftSQLServer2005(不是出于选择,但这就是生活)

在最初的应用程序中,我们几乎完全使用了符合ANSI-SQL的语句,但有一个显著的例外——我们相当频繁地使用MySQL的
group\u concat
函数

顺便说一句,group_concat是这样做的:给定一个员工姓名和项目表

SELECT empName, projID FROM project_members;
返回:

ANDY   |  A100
ANDY   |  B391
ANDY   |  X010
TOM    |  A100
TOM    |  A510
ANDY   |  A100 / B391 / X010
TOM    |  A100 / A510
。。。下面是您通过group_concat获得的信息:

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

ANDY   |  A100
ANDY   |  B391
ANDY   |  X010
TOM    |  A100
TOM    |  A510
ANDY   |  A100 / B391 / X010
TOM    |  A100 / A510
所以我想知道的是:有没有可能在SQL Server中编写一个用户定义的函数来模拟
group\u concat
的功能


我几乎没有使用UDF、存储过程或诸如此类的东西的经验,只是简单的SQL,所以请在解释太多的方面出错:)

没有真正简单的方法来做到这一点。尽管有很多想法

:


或者,如果数据可能包含以下代码中的字符(如
),则必须在部署之前在项目属性上设置PermissionLevel=External,并通过运行“ALTER DATABASE_name SET TRUSTHY ON”


收益率:A、B、C、D可能太晚了,现在还不能受益,但这不是最简单的方法吗

SELECT     empName, projIDs = replace
                          ((SELECT Surname AS [data()]
                              FROM project_members
                              WHERE  empName = a.empName
                              ORDER BY empName FOR xml path('')), ' ', REQUIRED SEPERATOR)
FROM         project_members a
WHERE     empName IS NOT NULL
GROUP BY empName

关于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
顺便问一下,使用“姓氏”是打字错误还是我不理解这里的一个概念


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

尝试了这些,但对于我在MS SQL Server 2005中的目的,以下内容非常有用,我在


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

我参加聚会可能有点晚,但这种方法对我有效,比合并方法更简单

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

要连接具有多个项目经理的项目中的所有项目经理名称,请执行以下操作:

SELECT a.project_id,a.project_name,Stuff((SELECT N'/ ' + first_name + ', '+last_name FROM projects_v 
where a.project_id=project_id
 FOR
 XML PATH(''),TYPE).value('text()[1]','nvarchar(max)'),1,2,N''
) mgr_names
from projects_v a
group by a.project_id,a.project_name
看看Github上的项目,我想我做的正是您要搜索的:

此项目包含一组SQLCLR用户定义聚合函数(SQLCLR UDA),它们共同提供与MySQL组_CONCAT函数类似的功能。有多个函数可确保基于所需功能的最佳性能


SQL Server 2017引入了一个新的聚合函数

连接字符串表达式的值并放置分隔符 它们之间的值。分隔符不添加在字符串的末尾

连接的元素可以通过在组内追加
来排序(按某些表达式排序)

对于2005-2016版我通常在接受的答案中使用XML方法

但是,在某些情况下,这可能会失败。例如,如果要连接的数据包含
CHAR(29)
您会看到

FOR XML无法序列化数据…因为它 包含XML中不允许的字符(0x001D)

可以处理所有字符的更健壮的方法是使用CLR聚合。但是,使用这种方法对连接的元素应用排序更为困难


在生产代码中,赋值给变量的方法是并且应该避免的。

对于我的谷歌同事来说,这里有一个非常简单的即插即用解决方案,在与更复杂的解决方案进行了一段时间的斗争后,它对我很有效:

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
这一切归功于:

更新2020:SQL Server 2016+JSON序列化和反序列化示例

OP提供的数据插入名为#project#u members的临时表中

drop table if exists #project_members;
create table #project_members(
  empName        varchar(20) not null,
  projID         varchar(20) not null);
go
insert #project_members(empName, projID) values
('ANDY', 'A100'),
('ANDY', 'B391'),
('ANDY', 'X010'),
('TOM', 'A100'),
('TOM', 'A510');
如何使用包含projID的嵌套数组将此数据序列化为单个JSON字符串

select empName, (select pm_json.projID 
                 from #project_members pm_json 
                 where pm.empName=pm_json.empName 
                 for json path, root('projList')) projJSON
from #project_members pm
group by empName
for json path;
select wj.empName, oj.projID
from
  #project_members_with_json wj
 cross apply
  openjson(wj.projJSON, '$.projList') with (projID    varchar(20)) oj;
结果

'[
  {
    "empName": "ANDY",
    "projJSON": {
      "projList": [
        { "projID": "A100" },
        { "projID": "B391" },
        { "projID": "X010" }
      ]
    }
  },
  {
    "empName": "TOM",
    "projJSON": {
      "projList": [
        { "projID": "A100" },
        { "projID": "A510" }
      ]
    }
  }
]'
如何将此数据从单个JSON字符串反序列化回其原始行和列

declare @json           nvarchar(max)=N'[{"empName":"ANDY","projJSON":{"projList":[{"projID":"A100"},
                                         {"projID":"B391"},{"projID":"X010"}]}},{"empName":"TOM","projJSON":
                                         {"projList":[{"projID":"A100"},{"projID":"A510"}]}}]';

select oj.empName, noj.projID 
from openjson(@json) with (empName        varchar(20),
                           projJSON       nvarchar(max) as json) oj
     cross apply openjson(oj.projJSON, '$.projList') with (projID    varchar(20)) noj;
结果

empName projID
ANDY    A100
ANDY    B391
ANDY    X010
TOM     A100
TOM     A510
empName projJSON
ANDY    {"projList":[{"projID":"A100"},{"projID":"B391"},{"projID":"X010"}]}
TOM     {"projList":[{"projID":"A100"},{"projID":"A510"}]}
empName projID
ANDY    A100
ANDY    B391
ANDY    X010
TOM     A100
TOM     A510
如何将唯一的empName持久化到表中,并将projID存储在嵌套的JSON数组中

drop table if exists #project_members_with_json;
create table #project_members_with_json(
  empName        varchar(20) unique not null,
  projJSON       nvarchar(max) not null);
go
insert #project_members_with_json(empName, projJSON) 
select empName, (select pm_json.projID 
                 from #project_members pm_json 
                 where pm.empName=pm_json.empName 
                 for json path, root('projList')) 
from #project_members pm
group by empName;
结果

empName projID
ANDY    A100
ANDY    B391
ANDY    X010
TOM     A100
TOM     A510
empName projJSON
ANDY    {"projList":[{"projID":"A100"},{"projID":"B391"},{"projID":"X010"}]}
TOM     {"projList":[{"projID":"A100"},{"projID":"A510"}]}
empName projID
ANDY    A100
ANDY    B391
ANDY    X010
TOM     A100
TOM     A510
如何从具有唯一empName和嵌套JSON数组列(包含projID的)的表反序列化

select empName, (select pm_json.projID 
                 from #project_members pm_json 
                 where pm.empName=pm_json.empName 
                 for json path, root('projList')) projJSON
from #project_members pm
group by empName
for json path;
select wj.empName, oj.projID
from
  #project_members_with_json wj
 cross apply
  openjson(wj.projJSON, '$.projList') with (projID    varchar(20)) oj;
结果

empName projID
ANDY    A100
ANDY    B391
ANDY    X010
TOM     A100
TOM     A510
empName projJSON
ANDY    {"projList":[{"projID":"A100"},{"projID":"B391"},{"projID":"X010"}]}
TOM     {"projList":[{"projID":"A100"},{"projID":"A510"}]}
empName projID
ANDY    A100
ANDY    B391
ANDY    X010
TOM     A100
TOM     A510

这个例子对我很有效,但我尝试进行另一次聚合,但没有成功,给了我一个错误:“在FROM子句中多次指定了相关名称'pre_trimmed'。“'pre_trimmed'只是子查询的别名。别名对于子查询是必需的,并且必须是唯一的,因此对于另一个子查询,请将其更改为唯一的…您是否可以显示一个没有表_名称作为列名的示例?这很令人困惑。有趣。我已经完成了手头的项目,但我将尝试一下这种方法。谢谢很好的技巧——唯一的问题是对于带有空格的姓氏,它将用分隔符替换空格。马克,我自己也遇到过这样的问题。不幸的是,在MSSQL跟上时代并引入GROUP_CONCAT之前,这是我能够为这里需要的东西想出的开销最少的方法。谢谢!这里有一个SQL FIDLE显示它的工作原理:几个方便的链接:这是一个老问题,但我喜欢。可能的重复-这篇文章的范围更广,所以我会选择这篇文章作为规范可能的重复,你如何知道应该按哪个顺序构建列表,例如,您显示的是A100/B391/X010,但鉴于关系数据库中没有隐含的排序,它也可能很容易是X010/A100/B391或任何其他组合。如果您问我,回答会很不友好,根本没有帮助。现在才看到这一点。。。我不是故意的,当时我对sql非常失望