【发布时间】:2015-09-25 06:41:32
【问题描述】:
我无法理解 CLR 用户定义聚合的工作原理。
我必须创建一些具有多个参数的自定义 CLR 聚合。 重点是根据第二个参数获取第一个参数的值。
例如,我的表中有以下值,对于每个 Type,我需要最年长的员工 Name:
Type | Name | Age
--------------------------------
Manager | emp 1 | 35
Manager | emp 2 | 42
Developer | emp 3 | 36
Developer | emp 4 | 45
Developer | emp 5 | 22
所以我想写一个这样的查询来使用我的程序集得到结果:
Select Type, dbo.fOldestEmployee(Name, Age) AS [Name]
From xxx
Group By Type
这会响应:
Type | Name
----------------------
Manager | emp 2
Developer | emp 4
看起来可以使用 CLR 用户定义的聚合,但我很难找到这种实现的具体示例。
目前我有这个。 我创建了一个类来收集数据,但是如何对它们进行排序(或做其他事情)?
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Text;
using System.Collections;
using System.IO;
[Serializable]
[SqlUserDefinedAggregate(
Format.UserDefined,
IsInvariantToOrder = false, // order changes the result
IsInvariantToNulls = false, // nulls change the result
IsInvariantToDuplicates = false, // duplicates change the result
MaxByteSize = -1)]
public struct sOlder
{
private List<MyData> _datas;
public void Init()
{
_datas = new List<MyData>();
}
public void Accumulate(SqlString valueField, SqlInt32 ValueInt)
{
if (!valueField.IsNull && !ValueInt.IsNull)
{
_datas.Add(new MyData
{
ValField = valueField.Value,
ValInt = ValueInt.Value
});
}
}
public void Merge (sOlder Group)
{
_datas.AddRange(Group._datas);
}
public SqlString Terminate ()
{
//...
}
public class MyData
{
public String ValField { get; set; }
public Int32 ValInt { get; set; }
}
}
有什么想法吗?
【问题讨论】:
-
这与聚合无关,您只需要编写一个语句,返回每种类型的最老员工。有很多方法可以做到这一点,并且所有方法都会比您尝试做的更快。检查例如ROW_NUMBER。如果您按类型分区并按年龄降序排列,则您正在寻找具有 ROW_NUMBER 1 的条目
-
感谢您的回复。我们其实是通过语句或者sql函数来做这种处理的。但这只是了解其工作原理的一个简单示例。
-
谁在大容量上做这个处理之王。我们通过使用例如Concatenate Aggregate 提高了很多性能
-
Select Type, MAX(Age) From xxx Group By Type
标签: c# sql-server .net-assembly sqlclr user-defined-aggregate