Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 CLR. Агрегатная функция с параметром для сортировки  [new]
Oleg Krivopusk
Member

Откуда: Хабаровск
Сообщений: 50
Здравствуйте!

Недавно начал изучать C#.

Создал агрегатную функцию для превращения "столбца" аббревиатур в строку. Все бы хорошо, но вот строка формируется в том порядке как занесены данные. А отсортировать результат нельзя при Group By.
Подскажите, пожалуйста код для сортировки по параметру (например, OrderGroup)

Код с параметром для разделителя ниже. А вот в каком месте попытаться сортировать - не могу понять. "Источника" данных не вижу.

[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.UserDefined, MaxByteSize = -1)]
public struct ConcatStrSeparator : IBinarySerialize
{
    private string _concatString;
    public void Init()
    {
        _concatString = string.Empty;
    }
    public void Accumulate(SqlString value, SqlString ch)
    {
        if (!value.IsNull)
        {
            _concatString += value.Value + ch.Value;
        }
        else
        {
            _concatString += "null" + ch.Value;
        }
    }
    public void Merge(ConcatStrSeparator @group)
    {
        _concatString += @group._concatString;
    }
    public SqlString Terminate()
    {
        return new SqlString(_concatString.Substring(0, _concatString.Length - 1));
    }
    public void Read(BinaryReader r)
    {
        _concatString = r.ReadString();
    }
    public void Write(BinaryWriter w)
    {
        w.Write(_concatString);
    }
}




P.S. Пытался на T-SQL сделать - работает, но скорость в стомильенов раз ниже. Тормоза жуткие.

...
select @result = (
  select iif(forgraphwork=1,'',ShortName) + Format(V,'#.##')
	From MyTable a 
	Left Join TypeHours  b on a.IdTypeHour = b.Id
	where TN = @TN and IdOrder = @IdOrder and Y = @Y and M = @M and D = @D
  Order by b.Order4Abrev
  for xml path(''), type
).value('.', 'varchar(255)')
...
17 сен 14, 02:34    [16583766]     Ответить | Цитировать Сообщить модератору
 Re: CLR. Агрегатная функция с параметром для сортировки  [new]
Oleg Krivopusk
Member

Откуда: Хабаровск
Сообщений: 50
Сделал так:

    [Serializable]
    [Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.UserDefined, MaxByteSize = -1)]
    public struct ConcatStrVsOrderParam : IBinarySerialize
    {
        private string _concatString;
        private Int32 _orderValue;
        public SortedList<SqlInt32,SqlString> _MyList;
        
        public void Init()
        {
            _concatString = string.Empty;
            _orderValue = 0;
            _MyList = new SortedList<SqlInt32,SqlString>();
        }

        public void Accumulate(SqlString value, SqlInt32 orderValue)
        {
            if ((!value.IsNull) && (!orderValue.IsNull))
            {
              _MyList.Add(orderValue.Value, value.Value);

              _concatString = "";
                
              foreach (KeyValuePair<SqlInt32, SqlString> kvp in _MyList)
              {
                  _concatString += (string)kvp.Value;
              };                
            }
            else
            {
                _concatString += "?";
            }
        }

        public void Merge(ConcatStrVsOrderParam @group)
        {
            _MyList.Add(@group._orderValue, @group._concatString);
        }

        public SqlString Terminate()
        {
            return new SqlString(_concatString);
        }

        public void Read(BinaryReader r)
        {
            _concatString = r.ReadString();
            _orderValue = r.ReadInt32();
        }
        
        public void Write(BinaryWriter w)
        {
            w.Write(_concatString);
            w.Write(_orderValue);
        }


Вроде работает. Может и деревянно?
17 сен 14, 07:31    [16583875]     Ответить | Цитировать Сообщить модератору
 Re: CLR. Агрегатная функция с параметром для сортировки  [new]
Ken@t
Member

Откуда: 大地
Сообщений: 3265
Oleg Krivopusk,

if ((!value.IsNull) && (!orderValue.IsNull))
            {
              _MyList.Add(orderValue.Value, value.Value);

              _concatString = "";
                
              foreach (KeyValuePair<SqlInt32, SqlString> kvp in _MyList)
              {
                  _concatString += (string)kvp.Value;
              };                
            }
            else
            {
                _concatString += "?";
            }

string.IsNullOrEmpty
_cancatstring - здесь не нужен, только тормоза, кроме того никогда не используйте такую кострукцию конкатинации строк, воспользуйтесь StringBuilder.
17 сен 14, 08:39    [16583996]     Ответить | Цитировать Сообщить модератору
 Re: CLR. Агрегатная функция с параметром для сортировки  [new]
Oleg Krivopusk
Member

Откуда: Хабаровск
Сообщений: 50
Ken@t,

Спасибо!

Я подозреваю, что в
public void Accumulate(SqlString value, SqlInt32 orderValue)


идет накопление и сколько строк обрабатывается, столько раз и выполняется.
Поэтому я каждый раз обнуляю _concatString
...  
_concatString = ""; 
...


там бы логично оставить только

 _MyList.Add(orderValue.Value, value.Value);

и перенести в
public SqlString Terminate()

само формирование строки с учетом сортировки
foreach (KeyValuePair<SqlInt32, SqlString> kvp in _MyList)
              {
                  _concatString += (string)kvp.Value; // Тут можно и StringBuilder использовать

              };                

Но там постоянно ругается на _MyList

System.NullReferenceException: Object reference not set to an instance of an object.
17 сен 14, 10:22    [16584336]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить