|
CLR Concatenate
|
|||
---|---|---|---|
#18+
здравствуйте алл помогите, пожалуйста. я совершенно не знаю язык C# но есть задачка из одной функции сделать более расширенную. помогите, пожалуйста. есть агрегатная функция, которая собирает из передаваемого массива в нее в одну строку через запятую. требуется ее чуть-модифицировать: сделать в функцию с тремя входящими параметрами - 1. соответственно массив как есть в настоящий момент. 2. параметр отвечающий за ограничение длины возвращаемой строки из всего набора через запятую. 3. знак разделитель. чтобы не жестко запятая была, а можно было бы управлять этим знаком. соответственно код существующей функции прилагается using System; using System.Collections.Generic; using System.Data.SqlTypes; using System.IO; using Microsoft.SqlServer.Server; [Serializable] [SqlUserDefinedAggregate(Format.UserDefined, MaxByteSize = 8000)] public struct fn_Concatenate : IBinarySerialize { private List<string> values; public void Init() { this.values = new List<string>(); } public void Accumulate(SqlString value) { this.values.Add(value.Value); } public void Merge(fn_Concatenate value) { this.values.AddRange(value.values.ToArray()); } public SqlString Terminate() { return new SqlString(string.Join(", ", this.values.ToArray())); } public void Read(BinaryReader r) { int itemCount = r.ReadInt32(); this.values = new List<string>(itemCount); for (int i = 0; i <= itemCount - 1; i++) { this.values.Add(r.ReadString()); } } public void Write(BinaryWriter w) { w.Write(this.values.Count); foreach (string s in this.values) { w.Write(s); } } } спасибо!!! ... |
|||
:
Нравится:
Не нравится:
|
|||
21.08.2013, 16:20 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
skyANA String.Join Method я дико извиняюсь. но мне бы код, чтобы я мог его скомпилировать. на этом мои знания и заканчиваются. еще раз извините ... |
|||
:
Нравится:
Не нравится:
|
|||
21.08.2013, 16:28 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
в идеале бы еще и управление сортировкой и группировкой данных на выходе. чтобы в перечисляемой строке одинаковые данные не попадались. но это уже верх моей наглости. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.08.2013, 09:45 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
Двоичникв идеале бы еще и управление сортировкой и группировкой данных на выходе. чтобы в перечисляемой строке одинаковые данные не попадались. но это уже верх моей наглости. Думаю, все-таки тебе придется открыть книжку по c# ... |
|||
:
Нравится:
Не нравится:
|
|||
22.08.2013, 09:57 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
либо никто не умеет, либо жлобы собрались на форуме. жалко помочь человеку? вот код возвращающий строку до 2 Гб, делиметр в параметре. а вот с сортировкой и группировкой может чуть попозже кину. если никто раньше не сделает. вдруг найдутся люди... using System; using System.Data; using System.Data.SqlClient; using System.Data.SqlTypes; using Microsoft.SqlServer.Server; using System.Text; [Serializable] [SqlUserDefinedAggregate( Format.UserDefined, IsInvariantToOrder = false, IsInvariantToNulls = true, IsInvariantToDuplicates = false, MaxByteSize = -1 )] public struct Concatenate : IBinarySerialize { private StringBuilder _accumulator; private string _delimiter; public Boolean IsNull; public void Init() { _accumulator = new StringBuilder(); _delimiter = string.Empty; } public void Accumulate(SqlChars item, SqlString delimiter) { // if we have an actual delimiter if ((!delimiter.IsNull) && (delimiter.Value.Length > 0)) { _delimiter = delimiter.Value; // accumulate delimiter if we have something already if (_accumulator.Length > 0) _accumulator.Append(delimiter.Value); } // if value is null, just add delimiter (above) and return if (item.IsNull) return; else { _accumulator.Append(item.Value); this.IsNull = false; } } public void Merge(Concatenate Group) { if (_accumulator.Length > 0 && Group._accumulator.Length > 0) _accumulator.Append(_delimiter); _accumulator.Append(Group._accumulator.ToString()); } public SqlChars Terminate() { return new SqlChars(_accumulator.ToString()); } void IBinarySerialize.Read(System.IO.BinaryReader r) { _delimiter = r.ReadString(); _accumulator = new StringBuilder(r.ReadString()); if (_accumulator.Length != 0) this.IsNull = false; } void IBinarySerialize.Write(System.IO.BinaryWriter w) { w.Write(_delimiter); w.Write(_accumulator.ToString()); } } ... |
|||
:
Нравится:
Не нравится:
|
|||
25.08.2013, 12:30 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
В MSSQL конкатенация строк обычно делается запросом: Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
... |
|||
:
Нравится:
Не нравится:
|
|||
25.08.2013, 14:33 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
Сон Веры Павловны, это конечно спасибо, но вопрос был именно в CLR ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2013, 14:36 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
Сон Веры ПавловныВ MSSQL конкатенация строк обычно делается запросом: Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
Я извиняюсь, но чем эта жесть через xml лучше классики? Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2013, 15:08 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
МСУЯ извиняюсь, но чем эта жесть через xml лучше классики? Тем, что эта классика, по сути - скалярка, и если надо будет сделать конкатенацию попутно с извлечением/агрегацией/etc. прочих данных, то ввиду того, что скалярка не будет заинлайнена в запрос, производительность заметно просядет. Если нужно просто сджойнить энную выборку в ХП - да, так нагляднее, во всех прочих случаях она проиграет в производительности - даже если эту скалярку объявить как schema-bound. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2013, 17:06 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
Сон Веры Павловны, не понял по поводу производительности... Что мешает сразу сформировать нужный рекордсет (фильтры и группировка) на SQL, а потом тупо собрать через накопительную переменную? ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2013, 17:21 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
модераторы, перенесите ветку в MS SQL, пожалуйста. спасибо я создал на основе предложенного варианта функцию Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.
и теперь при Код: sql 1.
я получаю SELECT failed because the following SET options have incorrect settings: 'ANSI_NULLS, QUOTED_IDENTIFIER'. Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or filtered indexes and/or query notifications and/or XML data type methods and/or spatial index operations. соответственно SET ANSI_WARNINGS OFF go SET ANSI_PADDING OFF go SET ANSI_NULLS OFF go SET QUOTED_IDENTIFIER OFF go даже ON ключ не помогает. что теперь нужно? чтобы заработало... ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2013, 17:44 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
МСУСон Веры Павловны, не понял по поводу производительности... Что мешает сразу сформировать нужный рекордсет (фильтры и группировка) на SQL, а потом тупо собрать через накопительную переменную? Ну вот простейший пример - вывести все таблицы базы с именами колонок в строчку для каждой таблицы: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
Каким боком тут приткнуть накопительную переменную, кроме как использовать её внутри скалярной функции? ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2013, 18:05 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
Сон Веры Павловны, подожди, ты писал про извлечение, агрегацию. Ну так извлекай и агрегируй. А потом конкатенируй и через разделитель накапливай в переменную, автору же нужно управлять этим разделителем. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2013, 21:56 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
Сон Веры Павловны, третий способ : http://codearticles.ru/articles/1861 ... |
|||
:
Нравится:
Не нравится:
|
|||
27.08.2013, 10:43 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
МСУ, Это самый неприемлемый способ - оверхед в виде объема перелопачиваемых данных (и, соответственно, нагрузка на сервер) растет по арифметической прогрессии в зависимости от числа записей в конкатенируемой выборке. Ради интереса провел тест. У нас в рабочей базе в sys.all_objects ~390 тыс. записей. Время отработки с накоплением в локальную переменную - 183 с. Время отработки через for xml path - 4 c. Отработки варианта с CTE я не дождался - прождал 5 минут, и решил не насиловать сервер. Почему первый способ (через переменную) настолько медленнее второго способа (через for xml) - не знаю, надо спросить в соответствующем разделе. Вроде план запроса с накоплением в переменную в разы проще плана с for xml, но факт проигрыша налицо. P.S. Проверялось на Код: sql 1.
Код: plaintext 1. 2. 3. 4. 5.
... |
|||
:
Нравится:
Не нравится:
|
|||
27.08.2013, 16:11 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
Сон Веры Павловны, для больших объемов for xml всех рвёт, не спорю. Я ратую за то, что для разных ситуаций могут применяться различные подходы. Накапливание в переменную много раз использовал, полет отличный. Надеюсь, согласишься, что задачи, в которых нужно на миллионных выборках в строчку через разделитель накрутить значения детализации - это дырка в башке архитектора подобного решения, а не в CTE. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.08.2013, 16:30 |
|
CLR Concatenate
|
|||
---|---|---|---|
#18+
Сон Веры ПавловныВ MSSQL конкатенация строк обычно делается запросом: Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
Шикарный вариант! Не знал, что так можно! Простестировал на больших объемах в сравнении с хорошо оптимизированной CLR агрегатом. Стояла задача конкатенации, поддерживающей сортировку, допускающей дупликаты ключей и значений, и превращающей null'ьные значения в пустые строки. Вариант с for xml бьет все рекорды. Причем, на лету коде можно использовать тонны вариаций, а вот чтобы вводить какие-то вариации в CLR реализацию, приходится пыхтеть, потеть и пузыриться. Огромное спасибо за пример! ... |
|||
:
Нравится:
Не нравится:
|
|||
10.06.2014, 11:13 |
|
|
start [/forum/topic.php?fid=20&msg=38377661&tid=1402829]: |
0ms |
get settings: |
9ms |
get forum list: |
12ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
39ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
50ms |
get tp. blocked users: |
1ms |
others: | 16ms |
total: | 150ms |
0 / 0 |