在Microsoft SQL Server 2005中模拟group_concat MySQL函数?

我正在尝试将基于MySQL的应用程序迁移到Microsoft SQL Server 2005(不是按需选择,但这就是生活)。 数据库

在原始应用程序中,咱们使用了几乎彻底符合ANSI-SQL的语句,但有一个明显的例外-咱们至关频繁地使用MySQL的group_concat函数。 安全

group_concatgroup_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;

返回: this

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

所以,我想知道的是:是否能够在SQL Server中编写一个模仿group_concat功能的用户定义函数? spa

我几乎没有使用UDF,存储过程或相似内容的经验,只是直接使用SQL,因此请在过多解释的旁边犯错:) code


#1楼

看看Github上的GROUP_CONCAT项目,我想我正是您要搜索的内容: orm

该项目包含一组SQLCLR用户定义的聚合函数(SQLCLR UDA),这些函数共同提供与MySQL GROUP_CONCAT函数相似的功能。 有多种功能可确保根据所需功能实现最佳性能。 xml


#2楼

使用下面的代码,您必须在部署以前在项目属性上设置PermissionLevel = External,并经过运行“ ALTER DATABASE database_name SET”来更改数据库以信任外部代码(请确保在其余地方阅读有关安全风险和替代方法的信息,例如证书)。值得信赖”。

using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using Microsoft.SqlServer.Server;

[Serializable]
[SqlUserDefinedAggregate(Format.UserDefined,
MaxByteSize=8000,
IsInvariantToDuplicates=true,
IsInvariantToNulls=true,
IsInvariantToOrder=true,
IsNullIfEmpty=true)]
    public struct CommaDelimit : IBinarySerialize
{


[Serializable]
 private class StringList : List<string>
 { }

 private StringList List;

 public void Init()
 {
  this.List = new StringList();
 }

 public void Accumulate(SqlString value)
 {
  if (!value.IsNull)
   this.Add(value.Value);
 }

 private void Add(string value)
 {
  if (!this.List.Contains(value))
   this.List.Add(value);
 }

 public void Merge(CommaDelimit group)
 {
  foreach (string s in group.List)
  {
   this.Add(s);
  }
 }

 void IBinarySerialize.Read(BinaryReader reader)
 {
    IFormatter formatter = new BinaryFormatter();
    this.List = (StringList)formatter.Deserialize(reader.BaseStream);
 }

 public SqlString Terminate()
 {
  if (this.List.Count == 0)
   return SqlString.Null;

  const string Separator = ", ";

  this.List.Sort();

  return new SqlString(String.Join(Separator, this.List.ToArray()));
 }

 void IBinarySerialize.Write(BinaryWriter writer)
 {
  IFormatter formatter = new BinaryFormatter();
  formatter.Serialize(writer.BaseStream, this.List);
 }
    }

我已经使用以下查询查询对此进行了测试:

SELECT 
 dbo.CommaDelimit(X.value) [delimited] 
FROM 
 (
  SELECT 'D' [value] 
  UNION ALL SELECT 'B' [value] 
  UNION ALL SELECT 'B' [value] -- intentional duplicate
  UNION ALL SELECT 'A' [value] 
  UNION ALL SELECT 'C' [value] 
 ) X

并产生:A,B,C,D


#3楼

可能为时已晚,如今没法受益,但这不是最简单的作事方法吗?

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

#4楼

关于哈迪曼(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

顺便说一句,使用“姓氏”是拼写错误仍是我在这里不理解这个概念?

不管如何,谢谢你们,由于它节省了我不少时间:)


#5楼

尝试了这些,但出于我在MS SQL Server 2005中的目的,如下是最有用的,我在xaprb上找到了

declare @result varchar(8000);

set @result = '';

select @result = @result + name + ' '

from master.dbo.systypes;

select rtrim(@result);

正如您所提到的,@ Mark对我来讲是空格字符。

相关文章
相关标签/搜索