sqlserver 创建自定义聚合函数

需求场景

当你想要在聚合阶段,对聚合字段做除了count、sum等操作一些复杂操作时候,怎么都没办法处理
要么就是写一个存储过程,一步步操作,但这也效率就太低了
最后的办法就是写一个自定义的聚合函数,来自定义处理聚合阶段的多个结果字段之间如何处理

如何开发

参考:https://www.cnblogs.com/volts0302/p/5545401.html
1)VS2022开发工具

2)选择聚合函数
我们可以看到除了自定义聚合函数,还可以写其他

3)实现聚合后其他的存在多个结果的字段通过+连接起来,代码
`using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.IO;
using System.Text;
using Microsoft.SqlServer.Server;

[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(
Format.UserDefined, //使用UserDefined 序列化格式
IsInvariantToNulls = true, //聚合是否与空值有关
IsInvariantToDuplicates = false, //聚合是否与重复值有关
IsInvariantToOrder = false, //聚合是否与顺序有关
MaxByteSize = 8000)]
public struct SqlAggregate1: IBinarySerialize
{
///


/// 定义变量
///

private StringBuilder intermediateResult;
public void Init()
{
// 在此处放置代码
intermediateResult = new StringBuilder();
}

public void Accumulate(SqlString Value,string contChar)
{
    // 在此处放置代码
    if (Value.IsNull) {
        return;
    }
    intermediateResult.Append(Value.ToString()).Append(contChar);
}

public void Merge (SqlAggregate1 Group)
{
    // 在此处放置代码
    this.intermediateResult.Append(Group.intermediateResult);
}

public SqlString Terminate ()
{
    // 在此处放置代码
    string output = string.Empty;
    //删除最后的,
    if (this.intermediateResult != null && this.intermediateResult.Length > 0) { 
        output = this.intermediateResult.ToString(0,this.intermediateResult.Length-1);
    }
    return output;
}

public void Read(BinaryReader r)
{
    intermediateResult = new StringBuilder(r.ReadString());
}

public void Write(BinaryWriter w)
{
    throw new NotImplementedException();
}

// 这是占位符成员字段
public int _var1;
}`

4)右键生成dll
几个配置项要注意

5)数据库中加载
use 你的库
DECLARE @hash AS BINARY(64) = (SELECT HASHBYTES('SHA2_512', (SELECT * FROM OPENROWSET (BULK 'C:\java\EMPI\CustomAgg.dll', SINGLE_BLOB) AS [Data])))
EXEC sp_add_trusted_assembly @hash
EXEC sp_configure 'clr enabled', 1
RECONFIGURE WITH OVERRIDE
CREATE ASSEMBLY SQL_Aggregate FROM 'C:\java\EMPI\CustomAgg.dll'
--drop ASSEMBLY SQL_Aggregate //这个是你写入错误,可以删除的命令
CREATE AGGREGATE SQL_Aggregate (@input nvarchar(200),@contChar nvarchar(1)) RETURNS nvarchar(max)
EXTERNAL NAME SQL_Aggregate.SqlAggregate1
--创建例子
create table tb(ID int,Name varchar(10))
insert into tb
select 1,'a'
union all select 1,'b'
union all select 2,'c'
union all select 2,'e'
union all select 3,'d'
select * from tb
select id,dbo.SQL_Aggregate([Name],'+') AS Test from tb group by id

posted @ 2022-09-14 15:43  王吉平  阅读(422)  评论(0编辑  收藏  举报