如何创建返回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
相关产品推荐
相关产品推荐

