You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建返回NVARCHAR类型的用户定义聚合函数?

实现自定义聚合函数:单值返回或多值返回'#'

方案一:无需自定义聚合,原生T-SQL直接实现

你可以直接在GROUP BY查询中用原生函数组合实现需求,无需创建自定义函数:

SELECT
    group_id, -- 替换为你的分组列
    CASE
        WHEN COUNT(DISTINCT target_column) = 1 THEN MAX(target_column)
        ELSE '#'
    END AS aggregated_result
FROM your_table -- 替换为你的表名
GROUP BY group_id;

逻辑说明:

  • COUNT(DISTINCT target_column)统计分组内目标列的不同值数量
  • 若数量为1,用MAX(target_column)获取该唯一值(用MIN效果相同)
  • 若数量大于1,返回#

方案二:封装为CLR自定义聚合函数(复用场景)

如果需要把这个逻辑封装成可复用的聚合函数,SQL Server需要借助CLR(公共语言运行时)实现,步骤如下:

1. 启用CLR集成

SQL Server默认禁用CLR,先执行以下命令开启:

sp_configure 'show advanced options', 1;
RECONFIGURE;
sp_configure 'clr enabled', 1;
RECONFIGURE;
GO

2. 编写CLR聚合类(C#示例)

创建C#类库项目,实现IUserDefinedAggregate和IBinarySerialize接口,处理分组内的逐行数据:

using System;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.IO;

[Serializable]
[SqlUserDefinedAggregate(
    Format.UserDefined,
    MaxByteSize = -1,
    IsInvariantToNulls = true,
    IsInvariantToDuplicates = true,
    IsInvariantToOrder = true
)]
public class SingleValueOrHash : IBinarySerialize
{
    private string _uniqueValue;
    private bool _hasMultipleValues;

    public void Init()
    {
        _uniqueValue = null;
        _hasMultipleValues = false;
    }

    public void Accumulate(SqlString value)
    {
        if (value.IsNull) return;
        
        var current = value.Value;
        if (_uniqueValue == null)
        {
            _uniqueValue = current;
        }
        else if (!_hasMultipleValues && !string.Equals(_uniqueValue, current, StringComparison.Ordinal))
        {
            _hasMultipleValues = true;
        }
    }

    public void Merge(SingleValueOrHash other)
    {
        if (other._hasMultipleValues)
        {
            _hasMultipleValues = true;
        }
        else if (other._uniqueValue != null)
        {
            if (_uniqueValue == null)
            {
                _uniqueValue = other._uniqueValue;
            }
            else if (!string.Equals(_uniqueValue, other._uniqueValue, StringComparison.Ordinal))
            {
                _hasMultipleValues = true;
            }
        }
    }

    public SqlString Terminate()
    {
        return _hasMultipleValues ? new SqlString("#") 
                                  : (_uniqueValue == null ? SqlString.Null : new SqlString(_uniqueValue));
    }

    public void Read(BinaryReader reader)
    {
        _hasMultipleValues = reader.ReadBoolean();
        _uniqueValue = reader.ReadString();
    }

    public void Write(BinaryWriter writer)
    {
        writer.Write(_hasMultipleValues);
        writer.Write(_uniqueValue ?? string.Empty);
    }
}

3. 编译并注册DLL

  • 编译C#代码生成DLL(例如CustomAgg.dll)
  • 将DLL放置到SQL Server可访问的本地路径,然后执行注册:
CREATE ASSEMBLY CustomAgg
FROM 'C:\SQL_Assemblies\CustomAgg.dll'
WITH PERMISSION_SET = SAFE;
GO

4. 创建自定义聚合函数

CREATE AGGREGATE dbo.my_agg(@mycol NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
EXTERNAL NAME CustomAgg.SingleValueOrHash;
GO

5. 使用自定义聚合函数

SELECT
    group_id,
    dbo.my_agg(target_column) AS aggregated_result
FROM your_table
GROUP BY group_id;

内容的提问来源于stack exchange,提问作者Samet Sökel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 14:43:29