Quantcast
Channel: SQL.ru: Microsoft SQL Server
Viewing all articles
Browse latest Browse all 7251

Group Coalesce

$
0
0
Здравствуйте,

мне нужно сделать групповую функцию Coalesce. Аналог Group_Concat.
+ Для чего мне это нужно
В разных папках у меня лежат неполные наборы файлов к определенному документу xml. По документу xml я нахожу лежащие рядом с ним в одной папке и относящиеся к нему файлы. Я их все заношу в табличку вида:
file_stream.xml file_stream.xml.sig file_stream.pdffile_stream.pdf.sig
0x514684135481 NULL 0x35434318 NULL
0x514684135481 0x51238431 NULL NULL
0x514684135481NULLNULL0x1483434843
Получается несколько строк, относящихся к одному документу 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
110.10.2010 0:00:00 NULL
2NULL




Подскажите, пожалуйста, что я не так сделал.

Viewing all articles
Browse latest Browse all 7251

Trending Articles