可以将CLR聚合与Hash Group提示一起使用吗?
我尝试了GROUP_CONCAT()聚合函数(您可以在codeplex http://groupconcat.codeplex.com/上找到它),但问题在于我尝试过的每个自定义聚合函数。
当我跑步时:
SELECT
Position,
dbo.GROUP_CONCAT(Name)
FROM TestTable
GROUP BY Position
OPTION (HASH GROUP)
我总是得到错误:
消息8622,级别16,状态1,行1查询处理器由于此查询中定义的提示而无法生成查询计划。重新提交 查询时没有指定任何提示,也没有使用SET FORCEPLAN。
以下是我可以在http://groupconcat.codeplex.com/找到的用于创建程序集的测试表和代码:
CREATE TABLE [dbo].[TestTable](
[Id] [int] NOT NULL,
[Name] [varchar](50) NULL,
[Position] [int] NULL
)
GO
INSERT [dbo].[TestTable] ([Id], [Name], [Position]) VALUES (1, N'dfgdfg', 1)
GO
INSERT [dbo].[TestTable] ([Id], [Name], [Position]) VALUES (2, N'dfdfg', 2)
GO
INSERT [dbo].[TestTable] ([Id], [Name], [Position]) VALUES (3, N'rgererg', 1)
GO
这是C#中的聚合函数定义:
[Serializable]
[SqlUserDefinedAggregate(Format.UserDefined,
MaxByteSize = -1,
IsInvariantToNulls = true,
IsInvariantToDuplicates = false,
IsInvariantToOrder = true,
IsNullIfEmpty = true)]
public struct GROUP_CONCAT : IBinarySerialize
{
private Dictionary<string, int> values;
public void Init()
{
this.values = new Dictionary<string, int>();
}
public void Accumulate([SqlFacet(MaxSize = 4000)] SqlString VALUE)
{
if (!VALUE.IsNull)
{
string key = VALUE.Value;
if (this.values.ContainsKey(key))
{
this.values[key] += 1;
}
else
{
this.values.Add(key, 1);
}
}
}
public void Merge(GROUP_CONCAT Group)
{
foreach (KeyValuePair<string, int> item in Group.values)
{
string key = item.Key;
if (this.values.ContainsKey(key))
{
this.values[key] += Group.values[key];
}
else
{
this.values.Add(key, Group.values[key]);
}
}
}
[return: SqlFacet(MaxSize = -1)]
public SqlString Terminate()
{
if (this.values != null && this.values.Count > 0)
{
StringBuilder returnStringBuilder = new StringBuilder();
foreach (KeyValuePair<string, int> item in this.values)
{
for (int value = 0; value < item.Value; value++)
{
returnStringBuilder.Append(item.Key);
returnStringBuilder.Append(",");
}
}
return returnStringBuilder.Remove(returnStringBuilder.Length - 1, 1).ToString();
}
return null;
}
public void Read(BinaryReader r)
{
int itemCount = r.ReadInt32();
this.values = new Dictionary<string, int>(itemCount);
for (int i = 0; i <= itemCount - 1; i++)
{
this.values.Add(r.ReadString(), r.ReadInt32());
}
}
public void Write(BinaryWriter w)
{
w.Write(this.values.Count);
foreach (KeyValuePair<string, int> s in this.values)
{
w.Write(s.Key);
w.Write(s.Value);
}
}
}