Здравствуйте,
мне нужно сделать групповую функцию Coalesce. Аналог
Group_Concat.
+ Для чего мне это нужно |
В разных папках у меня лежат неполные наборы файлов к определенному документу xml. По документу xml я нахожу лежащие рядом с ним в одной папке и относящиеся к нему файлы. Я их все заношу в табличку вида:
file_stream.xml | file_stream.xml.sig | file_stream.pdf | file_stream.pdf.sig | 0x514684135481 | NULL | 0x35434318 | NULL | 0x514684135481 | 0x51238431 | NULL | NULL | 0x514684135481 | NULL | NULL | 0x1483434843 |
| Получается несколько строк, относящихся к одному документу xml. Причем в некоторых строчках есть один документ, но нет другого. Групповой функцией Coalesce хочу собрать полный комплект документов. |
+ Я попробовал сделать ее с помощью clr |
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.IO;
namespace MSSQLServicesExtensionByFFFFF
{
/// <summary>
/// Пользовательская агрегатная функция, которая выбирает первое встретившееся не null значение. Аналог Coalesce
/// </summary>
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.UserDefined,
IsInvariantToDuplicates = true, //так как выбирается первое не null-значение, то не учитывает дубликаты
IsInvariantToNulls = true, //не учитывает null
IsInvariantToOrder = false, //используется первое встретившееся значение
IsNullIfEmpty = true, //возвращает null, если накполенное значение отсутствует
MaxByteSize = -1,
Name = "Coalesced")]
public struct Coalesced: IBinarySerialize
{
public void Init()
{
_firstNotNullVal = null;
IsNull = true;
}
public void Accumulate(Object Value)
{
if (IsNull && Value != null)
{
_firstNotNullVal = Value;
IsNull = false;
}
}
public void Merge(Coalesced Group)
{
if (IsNull && !Group.IsNull)
{
_firstNotNullVal = Group._firstNotNullVal;
IsNull = false;
}
}
public Object Terminate()
{
return IsNull ? SqlString.Null : _firstNotNullVal;
}
public void Read(BinaryReader r)
{
IsNull = r.ReadBoolean();
if(!IsNull)
_firstNotNullVal = r.ReadString();
}
public void Write(BinaryWriter w)
{
w.Write(IsNull);
if(!IsNull)
w.Write(_firstNotNullVal.ToString());
}
public Object _firstNotNullVal;
private bool IsNull;
}
}
|
В какой-то степени clr-функция работает, но не возвращает NULL так как должна бы.
+ Пример запроса и результат |
DECLARE @d DATE = CAST('20101010' AS DATE);
SELECT a AS Группа, Services.Coalesced(b) AS Объединение, NULL AS "Пример каким должен быть NULL"
FROM (VALUES(1,NULL),
(2,NULL),
(1,NULL),
(2,NULL),
(1,@d)
)AS D(a,b)
GROUP BY a;
Группа | Объединение | Пример каким должен быть NULL | 1 | 10.10.2010 0:00:00 | NULL | 2 | | NULL |
|
|
Подскажите, пожалуйста, что я не так сделал.