Обход запроса по нескольким группировкам

Опубликовал zfilin в раздел Программирование - Практика программирования

Хочу поделиться с вами небольшой "зарисовкой", которая помогает мне обходить выборку запроса, как бы пропуская некоторые группировки.

Хочу поделиться с вами небольшой "зарисовкой", которая помогает мне обходить выборку запроса, как бы пропуская некоторые группировки.
Что я имею в виду. Предположим, у нас есть запрос, который выбирает из регистра движения по номенклатуре в разрезе склада, номенклатуры, характеристики номенклатуры и документа движения. Вот как выглядит "плоская" выгрузка результата этого запроса:

Если в запросе указать итоги по складу, номенклатуре и характеристике номенклатуры и написать следующий код:

то обход будет производиться следующим образом:

Т.е. по первой группировке "Склад" внешний цикл (голубой) совершит одну итерацию, по второй группировке "Номенклатура" ("розовый" цикл) четыре итерации, в каждой из итераций "розового" цикла будет разное количество итераций "зеленого" цикла по группировке "ХарактеристикаНоменклатуры", и в конечном итоге будут выбраны все детальные записи ("серый" цикл), которые на рисунке я отмечать не стал, ибо лениво.

Но иногда хочется выбрать записи вот таким образом:

Т.е. так, чтобы внешний (голубой) цикл выбирал, как и положено, по группировке "Склад", а внутренний (зеленый) выбирал по некой "агрегатной" группировке "Номенклатура+ХарактеристикаНоменклатуры". Ну и дальше по необходимости детальные записи. Это было бы удобно, если бы вы, например, создавали документы по группировке "Склад", а второй "метагруппировкой" заполняли табличную часть каким-либо образом. Конечно, код, который приведен выше, справляется с этой задачей, но лично моя печаль в том, что там есть один вложенный цикл (розовый), который делается совершенно ненужным с точки зрения "изящества кода" как минимум. К тому же, когда таких группировок становится больше, например девять, мы видим совершенно "потрясающую" картину из девяти вложенных циклов.
Еще можно просто пропустить группировку "Номенклатура" и обходить результат запроса по группировкам "Склад - ХарактеристикаНоменклатуры - ДетальныеЗаписи". Но вот беда, в этом случае на уровне характеристики нет самой номенклатуры. Смотрите сами:

 

Получается, что на уровне выборки по складу номенклатуры еще нет, а на уровне выборки по характеристике ее... все еще нет. Бида.

Я точно знаю, что я не один такой, но у меня и у других коллег по несчастью как-то сам собой напрашивается вот такой код:


Код прекрасен всем, кроме того... что он не работает. Если когда-нибудь разгадаю это тайное послание фирмы 1С о "списке группировок", я обязательно с вами поделюсь. Сейчас же я знаю только то, что этот код мне не удалось заставить работать ни под каким соусом.

Но мы не ждем милости от природы и от 1С. А берем и сами делаем. Вот такой код работает нормально вполне:

Пара слов о функциях.
Функция "зфВыбратьПоГруппировкам" применяется вместо "ВыборкаЛалала.Выбрать()". Ей передается выборка, из которой нужно выбирать, и перечень группировок через запятую. При этом она возвращает некую "метавыборку". Ничего военного, просто соответствие с необходимыми данными.
Функция "зфСледующийПоГруппировкам" применяется вместо "ВыборкаОлоло.Следующий()". Ей передается та самая, открытая на предыдущем шаге "метавыборка" и возвращает она истину или ложь, как и штатный метод "Следующий".
Да. Внутри цикла вы можете смело получать родную 1С-овскую выборку нижнего уровня группировок, обратившись к элементу соответствия "Выборка". Вот так:

РоднаяВыборка1С = МетаВыборка["Выборка"];

Естественно, дальше родную выборку 1С можно хоть снова перебирать этими функциями, хоть выбирать штатными средствами.

Также не могу не сказать, что, в принципе, в функциях нет ничего нового и я тут не претендую на оригинальность или что-нибудь в таком духе. Думаю, что многие писали такие же функции, просто хотелось поделиться с уважаемым сообществом.
Они также не убирают вложенные циклы, просто немного иначе их организуют и скрывают. Т.е. в действительности все "лишние" циклы есть, но из кода это не очевидно.
Еще вполне понятно, что их использование будет менее производительным в смысле быстродействия, нежели использование вороха вложенных циклов. Я, конечно, старался написать пооптимальнее, но сами понимаете, накладные расходы будут.
Да, одна функция рекурсивная. По идее глубина рекурсии будет небольшой и равна количеству пропускаемых группировок плюс один, однако рекурсия есть рекурсия.
Ну и конечно, не исключен вариант, что я где-то накосячил. Если обнаружите - пишите, поправим.

Наконец сами функции:


Функция зфВыбратьПоГруппировкам(Выборка, Группировки, СИерархией = Ложь)

      
МетаВыборка = Новый Соответствие;

      
врОбходРезультата = ОбходРезультатаЗапроса.ПоГруппировкам;
       Если
СИерархией Тогда
              
врОбходРезультата = ОбходРезультатаЗапроса.ПоГруппировкамСИерархией;
       КонецЕсли;
      
МетаВыборка.Вставить("ОбходРезультата", врОбходРезультата);

      
МассивГруппировок = Новый Массив;
      
врСтрГруппировки = Группировки;
       Пока Истина Цикл
              
Поз = Найти( врСтрГруппировки, "," );
               Если
Поз = 0 Тогда
                      
МассивГруппировок.Добавить(СокрЛП(врСтрГруппировки));
                       Прервать;
               КонецЕсли;
              
МассивГруппировок.Добавить( СокрЛП( Лев(врСтрГруппировки,Поз-1) ) );
              
врСтрГруппировки = Сред( врСтрГруппировки, Поз+1 );
       КонецЦикла;

      
МетаВыборка.Вставить("Группировки", МассивГруппировок);

      
врВыборка = Выборка;
       Для
пц=0 По МассивГруппировок.Количество()-2 Цикл
              
врВыборкаУровня = врВыборка.Выбрать(врОбходРезультата, МассивГруппировок[пц]);
              
МетаВыборка.Вставить("_Выборка"+Строка(пц), врВыборкаУровня);
               Если не
врВыборкаУровня.Следующий() Тогда
                       Прервать;
               КонецЕсли;
              
врВыборка = врВыборкаУровня;
       КонецЦикла;
      
врВыборкаУровня = врВыборка.Выбрать(врОбходРезультата, МассивГруппировок[пц]);
      
МетаВыборка.Вставить("Выборка", врВыборкаУровня);
      
МетаВыборка.Вставить("_Выборка"+Строка(пц), врВыборкаУровня);

       Возврат
МетаВыборка;

КонецФункции
// зфВыбратьПоГруппировкам

Функция зфСледующийПоГруппировкам(МетаВыборка, Уровень = Неопределено)

       Если
Уровень = Неопределено Тогда
              
Уровень = МетаВыборка["Группировки"].Количество()-1;
       КонецЕсли;

       Если
Уровень < 0 Тогда
               Возврат Ложь;
       КонецЕсли;

      
врВыборка = МетаВыборка["_Выборка"+Строка(Уровень)];

       Если
врВыборка.Следующий() Тогда
               Возврат Истина;
       КонецЕсли;

       Если
зфСледующийПоГруппировкам(МетаВыборка, Уровень-1) Тогда
              
МассивГруппировок = МетаВыборка["Группировки"];
              
врВыборкаРодитель = МетаВыборка["_Выборка"+Строка(Уровень-1)];
              
врВыборка = врВыборкаРодитель.Выбрать(МетаВыборка["ОбходРезультата"],МассивГруппировок[Уровень]);
              
МетаВыборка["_Выборка"+Строка(Уровень)] = врВыборка;
               Если
Уровень = МассивГруппировок.Количество()-1 Тогда
                      
МетаВыборка["Выборка"] = врВыборка;
               КонецЕсли;
               Возврат
зфСледующийПоГруппировкам(МетаВыборка, Уровень);
       Иначе
               Возврат Ложь;
       КонецЕсли;

КонецФункции
// зфСледующийПоГруппировкам

Спасибо за внимание, а я желаю вам хорошего дня и хорошего кода.

Оригинал статьи в блоге автора

См. также

Лучшие комментарии

20. romansun 10.05.2012 16:14
(13) ох.. это ж писать надо :)

идея-то, в общем, простая. Вот такой упрощенно пример: есть таблица с кучей колонок (Организация, Контрагент, ДоговорКонтрагента, Номенклатура, Сумма, Количество и т.п.)

Нужно по этим строкам создавать документы, в шапку которых пихать реквизиты (Организация, Контрагент, ДоговорКонтрагента), в ТЧ пихать (Номенклатура, Сумма, Количество).

В запросе создаем поле "Ключ", которое определяем уникальными значениями для соответствующих интересующих нас полей. В нашем примере это "Организация", "Контрагент", "ДоговорКонтрагента". Т.е.

ВЫБРАТЬ
 ВложенныйЗапрос.Организация.Код + ВложенныйЗапрос.Контрагент.Код + ВложенныйЗапрос.ДоговорКонтрагента.Код КАК Ключ
...


(отмечу, что обычно договор это подчиненный справочник к контрагенту со сквозной нумерацией, т.е. все кода уникальны независимо от владельца, посему контрагент в этом ключе не нужен - договора будет достаточно. Но оставим для полноты примера :) )

данное поле "Ключ" будет однозначно уникальным для будущих документов. Т.е. мы получили составной уникальный ключ.

А дальше просто "итожим" по нему

ИТОГИ
   МАКСИМУМ(Организация),
   МАКСИМУМ(Контрагент),
   МАКСИМУМ(ДоговорКонтрагента)
ПО
   Ключ
...Показать Скрыть


максимум для этих полей определяем только для того, чтобы получить их в вернем уровне дерева, чтобы потом подставить в наш документ

в 1С-ном коде будет обычный цикл обхода дерева, где по итерации цикла на верхнем уровне создаем новый документ, а по итерациям на втором - заполняем его ТЧ. При этом нам совершенно не надо задумываться создавать ли новый документ на данной итерации цикла, или писать всё еще в предыдущий... и т.п. "приятные" вопросы.

И самое вкусное - если вдруг возникнет необходимость "доразбить" создаваемые документы еще по какому-нить полю, мы просто дописываем его в "Ключ" (например "... + БанковскиеСчета.Код КАК Ключ") и всё.

Таким образом можно делать достаточно сложные ключи. Можно использовать в качестве слагаемых, соответственно, результаты каких-то ВЫБОР КОГДА ТОГДА и т.п.

(14)
Хм. Насколько я понимаю, в запросе можно создать составной ключ склеиванием строк. Но поддерживается ли уникальность при конвертации ссылочных типов в строку? Т.е. вы получаете представление ссылки или просто представление, как наименование, код, НомерДок и т.д?


достаточно просто текстового представления уникального поля (группы полей) - код, наименование и т.п. С числами сложнее, а с датами еще сложнее, ибо их не сложишь как строку, да. А нормальной конвертации в 1С-ных запросах нет. Но числовые коды редко когда бывают, всё-таки. Насчет дат (да и чисел, кстати, тоже) за нас уже всё придумали (23 пост - отлично всё работает)
http://www.forum.mista.ru/topic.php?id=388253

Соответственно, дату (и число) можно представить строкой и приклеить к ключу.
# Ответить
12. romansun 26.04.2012 11:05
я последнее продолжительное время возвращаю запросом дерево, да, с составным ключом

циклы упрощаются до невозможности

и самое главное масштабирование кода также упрощается в разы! Достаточно изменить состав ключа в запросе - и всё, никакой 1С код в цикле менять не приходится

особенно помогла в этом метода "конвертации" даты в строку прям в запросе для успешного склеивания
Ответили: (13) (14) (17)
# Ответить
18. zfilin 28.04.2012 18:20
(15) i132, За "СледующийПоЗначениюПоля()" спасибо, нужно будет посмотреть.

А по поводу кода. Мне кажется или у вас там первая строка проглатывается? Когда вы в выборке дважды в подряд "Следующий()" вызываете?
Ну в целом, после первого "Следующий" выборку можно и на начало сбросить, так что принцип понятен.

Но вот именно от такого кода и хочется избавиться в первую очередь. Собственно, эти процедуры я и "затеял", чтобы уйти от "мониторинга момента смены ключа".
Чем мне не нравится такой подход, это во-первых тем, что логика алгоритма несколько "размазывается" по коду. Мы имеем заполнение внутри цикла, создание и запись документа там же, а еще такие же блоки за пределами цикла. Причем, когда мы записываем документ внутри цикла, имеется документ относящийся к предыдущей итерации выборки, а данные в выборке соответствуют уже новому. Все это, что ни говори, повышает сложность кода. Да, что я говорю, думаю все отписавшиеся не раз писали код, который мониторил бы смену одного из полей и в зависимости от этого что-то происходил.
А еще мне очень не нравится то, что код дублируется. Хорошо, когда это одна строка "ЗаполнитьЗначенияСвойств", но когда по смене ключа предусматриваются более обширные действия, блок в начале (до начала цикла) и блок в цикле нужно не забывать обновлять одновременно. Так же как и "Записать()", если нужна не просто запись, а еще какие-то финализирующие действия.
А хочется стройной конструкции, где на одном уровне вложенности документ создавался бы, затем как-то заполнялся (следующая вложенность) и потом на том же уровне и записывался. Без разделения и дублирования.
Ответили: (19)
+ 1 [ i132; ]
# Ответить

Комментарии

1. zfilin 24.04.2012 21:50
В основном блоге коллега советует для данного примера применить к полю "Номенклатура" агрегатную функцию МАКСИМУМ.

Не пробовал, но почему ему не работать?
Ответили: (16)
# Ответить
2. Новиков 24.04.2012 23:44
Непонятно мне, а почему нельзя подготовить текст запроса таким образом чтобы получить простую выборку для простого обхода вот без этих всех квадратных треуголок? )
Ответили: (3)
# Ответить
3. zfilin 25.04.2012 00:01
(2) Новиков, Да, почему ж нельзя? Можно, конечно! Более того, это было бы даже лучше и быстрее.
Но иногда приходится и с треуголками. =)

А предложите свой вариант для такого обхода?
Ответили: (4)
# Ответить
4. Новиков 25.04.2012 00:06
(3) zfilin, я признаться, уже забыл, когда руками обходил результат запроса с группировками. Я обычно делаю базовую схему компоновки, и при помощи настроек компоновки (двигаю группировки вверх и вниз) получаю нужный резалт. И уже его как-то обрабатываю. Т.е. даже текст запроса никакого не нужно собирать. А Ваш вариант - он наверное крут, я не спорю. И наверное даже где-то находит применение. Вот и хотелось бы узнать - где! :%)
Ответили: (5)
# Ответить
5. zfilin 25.04.2012 00:22
(4) Новиков, А! СКД. Да, я тоже люблю скормить данные СКД, а потом получить их в нужно виде и по ним ходить. Но, вот недавно решил выбрать просто запросом и просто ходить по группировкам без СКД. Как-раз документы создавал. Так и применял.
Глупо было бы утверждать, что это единственный и уникальный способ и я сейчас выдам прям такую исключительную ситуацию, где запрос применить можно, а СКД нельзя.
С другой стороны какое-то внутреннее стремление к простоте протестует против того, чтобы "городить ЦЕЛУЮ СКД", когда надо просто обойти группировки простого запроса. Если бы это было возможно реализовать штатными средствами (как в не работающем примере), это был бы win. А поскольку сами функции получились достаточно "мозгачными", то это, конечно не win, а так - посокрушаться.
# Ответить
6. Yashazz 25.04.2012 12:21
Хм, никогда не пользуюсь указанным обходом. Работаю с плоской таблицей значений, можно как угодно выкручивать, сортировать и обходить, безо всяких доп.функций и страшных вложений циклов. В самом хитром случае учреждаются доп.колонки для управления обходом (прям в запросе, или одним обходом таблицы), а дальше рулёжка уже по ним.
Да, и СКД рулит, конечно. Чего её "городить", дело-то простое, а выигрыш иной раз нехилый.
Ответили: (17)
# Ответить
7. dandrontiy 25.04.2012 13:00
Круто, но применение непонятно.
И мне почему то удобней не выборками пользоваться, а ТаблицаЗначений = Запрос.Выполнить().Выгрузить();
И мне кажется это к тому же просто быстрее. Как раз применимо для случая, когда надо что-то чем то заполнить, нет разве ?
# Ответить
8. karakozov 25.04.2012 13:45
Решение конечно для конкретной задачи, такой подход возможно имеет смысл в ситуации когда таблица имеет очень большой объем.И выбирать ее несколько раз для каждой выборки в рамках одной процедуры очень долго.Может быть конечно так разъяснено что не совсем понятно цель.В общем все от ситуации.
Ответили: (9)
# Ответить
9. Yashazz 25.04.2012 16:22
(8) Вопрос знатокам - выборка, полученная из результата запроса методом "Выбрать", или сам результат, кэшируется где-либо или болтается в оперативке? Если да, то в клиентской или где?
# Ответить
10. zfilin 25.04.2012 22:18
Друзья, но когда мне нужно обойти плоскую таблицу, мне же нужно понимать момент, когда у меня появляется другой склад в первой колонке, чтобы, если взять уже приведенный пример, создать новый документ с ДРУГИМ складом. Как же это реализовать в плоской выборке?
Т.е. тот случай, когда на разных "уровнях группировок" реализуется разное поведение, разный код.
+ 1 [ Gesperid; ]
# Ответить
11. zfilin 25.04.2012 22:20
Т.е. я сейчас не защищаю свои функции, но интересен сам принцип.
# Ответить
12. romansun 26.04.2012 11:05
я последнее продолжительное время возвращаю запросом дерево, да, с составным ключом

циклы упрощаются до невозможности

и самое главное масштабирование кода также упрощается в разы! Достаточно изменить состав ключа в запросе - и всё, никакой 1С код в цикле менять не приходится

особенно помогла в этом метода "конвертации" даты в строку прям в запросе для успешного склеивания
Ответили: (13) (14) (17)
# Ответить
13. MGraf 27.04.2012 12:14
(12) romansun, напишите пожалуйста публикацию! Хотя бы пару строк с примером :)
Ответили: (20)
+ 1 [ AllexSoft; ]
# Ответить
14. zfilin 27.04.2012 13:43
(12) romansun, Хм. Насколько я понимаю, в запросе можно создать составной ключ склеиванием строк. Но поддерживается ли уникальность при конвертации ссылочных типов в строку? Т.е. вы получаете представление ссылки или просто представление, как наименование, код, НомерДок и т.д?
Ответили: (20)
# Ответить
15. i132 28.04.2012 15:34
Если нет пустых характеристик, можно сделать запрос без группирповки итогов и воспользоваться методом Выборка.СледующийПоЗначениюПоля()

Описание метода на ИТС

либо как предложил Новиков в (2) прямой запрос, без группировок остортировать по списку полей шапки:
СтруктураУникальнойШапки = Новый Структура("Поле1,Поле2,Поле3");

Док = Неопределено; //Лучше объявить переменную до цикла, заодно проверим первый вход
Пока выборка.Следующий() Цикл
   ФлНоваяШапка =Ложь;
   Для каждого ПолеШапки из СтруктураУникальнойШапки Цикл
      Если НЕ ПолеШапки.Значение= выборка[ПолеШапки.Ключ] Тогда
		Если Док = Неопределено тогда 
		 	Док.Записать();
		КонецЕсли;	
         ЗаполнитьЗначенияСвойств(СтруктураУникальнойШапки,Выборка);
         Док = СоздатьДокПоШапке(СтруктураУникальнойШапки);
         Прервать;
      КонецЕсли;   
   КонецЦикла;   
   НоваяСтрока = Док.(ТабЧасть).Добавить();
   Док = ЗаполнитьЗначенияСвойств(НоваяСтрока,Выборка);
КонецЦикла;   

Если НЕ Док = Неопределено тогда 
	Док.Записать();
КонецЕсли;
...Показать Скрыть
Ответили: (18)
# Ответить
16. i132 28.04.2012 16:08
(1) zfilin, Максимум при группировке по Характеристики не поможет, если есть пустые характеристики.
# Ответить
17. EfiopReal 28.04.2012 17:55
(6) Yashazz,
Согласен с вами, но при большом объеме иногда удобнее прогуливаться по иерархии.

Как раз на прошлой неделе столкнулся с такой проблемой, делал перенос с 7.7 на 8.2 (да знаю, что есть куча обработок и Конвертация данных, которую пока не освоил к сожалению), каждый раз делать запросы или сортировать/обходить таблицу со всей номенклатурой, контрагентами и т.д. накладно (хотя какая разница, один раз перенос будет).
Автору + - еще одно интересное решение в копилку, думаю пригодится, хотя использовать буду редко.

(12) romansun,
Спасибо за наводку.
# Ответить
18. zfilin 28.04.2012 18:20
(15) i132, За "СледующийПоЗначениюПоля()" спасибо, нужно будет посмотреть.

А по поводу кода. Мне кажется или у вас там первая строка проглатывается? Когда вы в выборке дважды в подряд "Следующий()" вызываете?
Ну в целом, после первого "Следующий" выборку можно и на начало сбросить, так что принцип понятен.

Но вот именно от такого кода и хочется избавиться в первую очередь. Собственно, эти процедуры я и "затеял", чтобы уйти от "мониторинга момента смены ключа".
Чем мне не нравится такой подход, это во-первых тем, что логика алгоритма несколько "размазывается" по коду. Мы имеем заполнение внутри цикла, создание и запись документа там же, а еще такие же блоки за пределами цикла. Причем, когда мы записываем документ внутри цикла, имеется документ относящийся к предыдущей итерации выборки, а данные в выборке соответствуют уже новому. Все это, что ни говори, повышает сложность кода. Да, что я говорю, думаю все отписавшиеся не раз писали код, который мониторил бы смену одного из полей и в зависимости от этого что-то происходил.
А еще мне очень не нравится то, что код дублируется. Хорошо, когда это одна строка "ЗаполнитьЗначенияСвойств", но когда по смене ключа предусматриваются более обширные действия, блок в начале (до начала цикла) и блок в цикле нужно не забывать обновлять одновременно. Так же как и "Записать()", если нужна не просто запись, а еще какие-то финализирующие действия.
А хочется стройной конструкции, где на одном уровне вложенности документ создавался бы, затем как-то заполнялся (следующая вложенность) и потом на том же уровне и записывался. Без разделения и дублирования.
Ответили: (19)
+ 1 [ i132; ]
# Ответить
19. i132 28.04.2012 19:25
(18) >первая строка проглатывается
упс, спасибо, не заметил действительно обработку первой строки пропустил. старый пост (15) переписал.
# Ответить
20. romansun 10.05.2012 16:14
(13) ох.. это ж писать надо :)

идея-то, в общем, простая. Вот такой упрощенно пример: есть таблица с кучей колонок (Организация, Контрагент, ДоговорКонтрагента, Номенклатура, Сумма, Количество и т.п.)

Нужно по этим строкам создавать документы, в шапку которых пихать реквизиты (Организация, Контрагент, ДоговорКонтрагента), в ТЧ пихать (Номенклатура, Сумма, Количество).

В запросе создаем поле "Ключ", которое определяем уникальными значениями для соответствующих интересующих нас полей. В нашем примере это "Организация", "Контрагент", "ДоговорКонтрагента". Т.е.

ВЫБРАТЬ
 ВложенныйЗапрос.Организация.Код + ВложенныйЗапрос.Контрагент.Код + ВложенныйЗапрос.ДоговорКонтрагента.Код КАК Ключ
...


(отмечу, что обычно договор это подчиненный справочник к контрагенту со сквозной нумерацией, т.е. все кода уникальны независимо от владельца, посему контрагент в этом ключе не нужен - договора будет достаточно. Но оставим для полноты примера :) )

данное поле "Ключ" будет однозначно уникальным для будущих документов. Т.е. мы получили составной уникальный ключ.

А дальше просто "итожим" по нему

ИТОГИ
   МАКСИМУМ(Организация),
   МАКСИМУМ(Контрагент),
   МАКСИМУМ(ДоговорКонтрагента)
ПО
   Ключ
...Показать Скрыть


максимум для этих полей определяем только для того, чтобы получить их в вернем уровне дерева, чтобы потом подставить в наш документ

в 1С-ном коде будет обычный цикл обхода дерева, где по итерации цикла на верхнем уровне создаем новый документ, а по итерациям на втором - заполняем его ТЧ. При этом нам совершенно не надо задумываться создавать ли новый документ на данной итерации цикла, или писать всё еще в предыдущий... и т.п. "приятные" вопросы.

И самое вкусное - если вдруг возникнет необходимость "доразбить" создаваемые документы еще по какому-нить полю, мы просто дописываем его в "Ключ" (например "... + БанковскиеСчета.Код КАК Ключ") и всё.

Таким образом можно делать достаточно сложные ключи. Можно использовать в качестве слагаемых, соответственно, результаты каких-то ВЫБОР КОГДА ТОГДА и т.п.

(14)
Хм. Насколько я понимаю, в запросе можно создать составной ключ склеиванием строк. Но поддерживается ли уникальность при конвертации ссылочных типов в строку? Т.е. вы получаете представление ссылки или просто представление, как наименование, код, НомерДок и т.д?


достаточно просто текстового представления уникального поля (группы полей) - код, наименование и т.п. С числами сложнее, а с датами еще сложнее, ибо их не сложишь как строку, да. А нормальной конвертации в 1С-ных запросах нет. Но числовые коды редко когда бывают, всё-таки. Насчет дат (да и чисел, кстати, тоже) за нас уже всё придумали (23 пост - отлично всё работает)
http://www.forum.mista.ru/topic.php?id=388253

Соответственно, дату (и число) можно представить строкой и приклеить к ключу.
# Ответить
21. DoctorRoza 17.05.2012 09:46
Достаточно интересная статья, написано доходчиво и наглядно, сразу чувствуется высокий уровень автора! Предложенная идея больше смахивает на "лабораторную" раскопку 1С.
# Ответить
22. RainyAugust22 12.11.2012 07:27
хорошая статья,спасибо за инфу.
# Ответить
23. xomaq 12.11.2012 08:26
Огромное спасибо автору!!
Как раз сегодня мучился с подобной задачей. С кодом, приведенным автором, у меня все заработало!!
Респект и уважуха!!!
# Ответить
24. kit 23.11.2012 00:27
Хорошая статья. Тоже сижу разбираюсь с обходом группировок в запросе, а тут как раз в тему.
# Ответить
25. Evgen.Ponomarenko 13.08.2013 13:01
Действительно, актуально!
# Ответить
26. dimk@a 14.08.2013 10:56
Спасибо, хорошая статья. И в обсуждении как всегда много важного!
# Ответить
27. olbu 08.10.2015 12:31
А если переделать запрос та вот так:
ВЫБРАТЬ
	ТоварыНаСкладахОстатки.Склад КАК Склад,
	ТоварыНаСкладахОстатки.Номенклатура,
	ТоварыНаСкладахОстатки.ХарактеристикаНоменклатуры,
	ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток
ИЗ
	РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахОстатки
ИТОГИ
	СУММА(КоличествоОстаток)
ПО
	Склад
...Показать Скрыть


Верхняя группировка будет по складу, а нижняя - по номенклатуре + характеристике.
Или я не верно понял?
# Ответить
28. zfilin 09.10.2015 15:46
В таком простом случае, да сработает. Но это все же немного не то.
А если две составных группировки?
Например склад+контрагент и товар+характеристика.
# Ответить
29. EvgeniuXP 04.02.2016 23:14
Вот вам применение: есть документы, там 13 реквизитов, надо выявить одинаковые документы, если их два и более то один провести, остальные пометить на удаление. Методом группировок мы отсеиваем одинаковые, оставляем только одинаковые два и более документа, потом группируем по всем 13 реквизитам и на выходе имеем на самом нижнем уровне одинаковые записи двух и более документов. При первом входе проводим, при втором и последующих - метим на удаление.
# Ответить
Внимание! За постинг в данном форуме $m не начисляются.
Внимание! Для написания сообщения необходимо авторизоваться
Текст сообщения*
Прикрепить файл






IE 2016