Custom aggregates are as fast as built in T-SQL aggregates like MAX(), SUM(), etc..
Here is the C# source code for an aggregate that concatenates short strings:
using System; using System.Text; using System.IO; using System.Data; using System.Data.SqlClient; using System.Data.SqlTypes; using Microsoft.SqlServer.Server; [Serializable] [SqlUserDefinedAggregate( Format.UserDefined, //use clr serialization to serialize the intermediate result IsInvariantToNulls = true, //optimizer property IsInvariantToDuplicates = false, //optimizer property IsInvariantToOrder = false, //optimizer property MaxByteSize = 8000) //maximum size in bytes of persisted value ] public struct Concatenate : IBinarySerialize { private StringBuilder _IntermediateResult; // 8000 - 2 control bytes - 4 bytes for 2 UTF-16 characters = 7994 private const int _MaxSize = 7994; public void Init() { _IntermediateResult = new StringBuilder(); } public void Accumulate(SqlString value) { if (!value.IsNull && (_IntermediateResult.Length + value.GetUnicodeBytes().Length < _MaxSize)) { _IntermediateResult.Append(value.Value).Append(", "); } } public void Merge(Concatenate group) { if ((_IntermediateResult.Length + group._IntermediateResult.Length) < _MaxSize) { _IntermediateResult.Append(group._IntermediateResult); } } public SqlString Terminate() { string output = String.Empty; // Delete the trailing comma and space, if any if (_IntermediateResult != null && _IntermediateResult.Length > 1) { output = _IntermediateResult.ToString(0, _IntermediateResult.Length - 2); } return new SqlString(output); } public void Read(BinaryReader reader) { _IntermediateResult = new StringBuilder(reader.ReadString()); } public void Write(BinaryWriter writer) { writer.Write(_IntermediateResult.ToString()); } }
And here it is in action:
CREATE AGGREGATE Concatenate (@input nvarchar(4000)) RETURNS nvarchar(max) EXTERNAL NAME SqlClr.Concatenate GO SELECT Title, dbo.Concatenate(FirstName) AS [First Names] FROM Person.Contact GROUP BY Title Title First Names -------- --------------------------------------------- Sr. José, Jésus, Anibal, José, Luis, Gustavo, Ciro, Humberto, Alvaro, Adrian, Ramón Sra. Janeth, Pilar, Janaina Barreiro Gambaro [...]
No comments:
Post a Comment