Итоги по объединенной совокупности группировок в запросе

18.11.20

Разработка - Запросы

Способ формирования итогов в запросе по совокупности группировок, объединенных в единый набор, при помощи функции АВТОНОМЕРЗАПИСИ.

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

Такая задача решается легко, путем использования ключевого слова ИТОГИ в запросе:

ВЫБРАТЬ
	ТаблицаТоваров.Контрагент КАК Контрагент,
	ТаблицаТоваров.Номенклатура КАК Номенклатура,
	ТаблицаТоваров.Количество КАК Количество,
	ТаблицаТоваров.Сумма КАК Сумма
ИЗ
	&ТаблицаТоваров КАК ТаблицаТоваров
ИТОГИ
	СУММА(Сумма)
ПО
	Контрагент


Затем результат запроса обходим по группировкам и создаем документы:

ВыборкаПоКонтрагентам = Запрос.Выполнить.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Пока ВыборкаПоКонтрагентам.Следующий() Цикл
	
	// Заполнение шапки
	
	ДетальныеЗаписи = ВыборкаПоКонтрагентам.Выбрать();
	
	Пока ДетальныеЗаписи.Следующий() Цикл
		// Заполнение ТЧ товаров
	КонецЦикла;
	
КонецЦикла;


Усложним задачу, добавив в исходную таблицу колонку "Договор".

Теперь каждая отдельная реализация должна объединять строки с одинаковым набором значений Контрагент-Договор. Для того чтобы это учесть, можно добавить в запрос итоги по полю договор. При обходе результата запроса у нас появится еще один вложенный цикл.

ВыборкаПоКонтрагентам = Запрос.Выполнить.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Пока ВыборкаПоКонтрагентам.Следующий() Цикл

	ВыборкаПоДоговорам = ВыборкаПоКонтрагентам.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

	Пока ВыборкаПоДоговорам.Следующий() Цикл
		
		// Заполнение шапки
		
		ДетальныеЗаписи = ВыборкаПоДоговорам.Выбрать();
		
		Пока ДетальныеЗаписи.Следующий() Цикл
			// Заполнение ТЧ товаров
		КонецЦикла;
		
	КонецЦикла;
	
КонецЦикла;


Добавим в таблицу еще пару полей. Например, "Организация" и "Грузоотправитель". Реализация теперь создается на каждый набор Организация-Контрагент-Грузоотправитель-Договор. Если действовать тем же методом, добавляя итоговые поля в запрос, при обработке результата мы получим цикл пятого уровня вложенности:

ВыборкаПоОрганизациям = Запрос.Выполнить.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Пока ВыборкаПоОрганизациям.Следующий() Цикл

	ВыборкаПоКонтрагентам = ВыборкаПоОрганизациям.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

	Пока ВыборкаПоКонтрагентам.Следующий() Цикл

		ВыборкаПоГрузополучателям = ВыборкаПоКонтрагентам.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

		Пока ВыборкаПоГрузополучателям.Следующий() Цикл
				
			ВыборкаПоДоговорам = ВыборкаПоГрузополучателям.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

			Пока ВыборкаПоДоговорам.Следующий() Цикл
				
				// Заполнение шапки
				
				ДетальныеЗаписи = ВыборкаПоДоговорам.Выбрать();
				
				Пока ДетальныеЗаписи.Следующий() Цикл
					// Заполнение ТЧ товаров
				КонецЦикла;
				
			КонецЦикла;
			
		КонецЦикла;
		
	КонецЦикла;
	
КонецЦикла;


Вид этой конструкции вызывает, мягко говоря, негативные эмоции.
А ведь группировочных полей может быть еще больше...
Для того чтобы избежать матрешки из циклов, нужно присвоить каждой связке Организация-Контрагент-Грузоотправитель-Договор какой-то идентификатор и производить группировку по всему набору, а не по каждому полю в отдельности. В рамках языка запросов это можно сделать при помощи функции АВТОНОМЕРЗАПИСИ. Для нашего примера запрос должен выглядеть так:

ВЫБРАТЬ
	ТаблицаТоваров.Организация КАК Организация,
	ТаблицаТоваров.Контрагент КАК Контрагент,
	ТаблицаТоваров.Грузополучатель КАК Грузополучатель,
	ТаблицаТоваров.Договор КАК Договор,
	ТаблицаТоваров.Номенклатура КАК Номенклатура,
	ТаблицаТоваров.Количество КАК Количество,
	ТаблицаТоваров.Сумма КАК Сумма
ПОМЕСТИТЬ ВТ_ИсходнаяТаблица
ИЗ
	&ТаблицаТоваров КАК ТаблицаТоваров

ИНДЕКСИРОВАТЬ ПО
	Организация,
	Контрагент,
	Грузополучатель,
	Договор
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
	ВТ_ИсходнаяТаблица.Организация КАК Организация,
	ВТ_ИсходнаяТаблица.Контрагент КАК Контрагент,
	ВТ_ИсходнаяТаблица.Грузополучатель КАК Грузополучатель,
	ВТ_ИсходнаяТаблица.Договор КАК Договор,
	АВТОНОМЕРЗАПИСИ() КАК ИдентификаторНабора
ПОМЕСТИТЬ ВТ_РеквизитыШапки
ИЗ
	ВТ_ИсходнаяТаблица КАК ВТ_ИсходнаяТаблица

ИНДЕКСИРОВАТЬ ПО
	Организация,
	Грузополучатель,
	Контрагент,
	Договор
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	ВТ_РеквизитыШапки.ИдентификаторНабора КАК ИдентификаторНабора,
	ВТ_РеквизитыШапки.Организация КАК Организация,
	ВТ_РеквизитыШапки.Контрагент КАК Контрагент,
	ВТ_РеквизитыШапки.Грузополучатель КАК Грузополучатель,
	ВТ_РеквизитыШапки.Договор КАК Договор,
	ВТ_ИсходнаяТаблица.Номенклатура КАК Номенклатура,
	ВТ_ИсходнаяТаблица.Количество КАК Количество,
	ВТ_ИсходнаяТаблица.Сумма КАК Сумма
ИЗ
	ВТ_РеквизитыШапки КАК ВТ_РеквизитыШапки
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ИсходнаяТаблица КАК ВТ_ИсходнаяТаблица
		ПО ВТ_РеквизитыШапки.Организация = ВТ_ИсходнаяТаблица.Организация
			И ВТ_РеквизитыШапки.Контрагент = ВТ_ИсходнаяТаблица.Контрагент
			И ВТ_РеквизитыШапки.Грузополучатель = ВТ_ИсходнаяТаблица.Грузополучатель
			И ВТ_РеквизитыШапки.Договор = ВТ_ИсходнаяТаблица.Договор
ИТОГИ
	МАКСИМУМ(Организация),
	МАКСИМУМ(Контрагент),
	МАКСИМУМ(Грузополучатель),
	МАКСИМУМ(Договор),
	СУММА(Сумма)
ПО
	ИдентификаторНабора


Воспользовавшись функцией АВТОНОМЕРЗАПИСИ, мы идентифицировали все наборы Организация-Контрагент-Грузоотправитель-Договор и выполнили группировку в рамках целого набора, а не по каждому полю отдельно.
Код обработки такого запроса выглядит так же просто, как и в первоначальном случае с единственным группировочным полем:

ВыборкаПоНаборам = Запрос.Выполнить.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Пока ВыборкаПоНаборам.Следующий() Цикл
	
	// Заполнение шапки
	
	ДетальныеЗаписи = ВыборкаПоНаборам.Выбрать();
	
	Пока ДетальныеЗаписи.Следующий() Цикл
		// Заполнение ТЧ товаров
	КонецЦикла;
	
КонецЦикла;


 

язык запросов АВТОНОМЕРЗАПИСИ группировка ИТОГИ

См. также

SALE! 20%

Infostart Toolkit: Инструменты разработчика 1С 8.3 на управляемых формах

Инструментарий разработчика Роли и права Запросы СКД Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

13000 10400 руб.

02.09.2020    121593    670    389    

710

Для чего используют конструкцию запроса "ГДЕ ЛОЖЬ" в СКД на примере конфигурации 1С:ERP

Запросы СКД Платформа 1С v8.3 Запросы Система компоновки данных 1С:ERP Управление предприятием 2 Бесплатно (free)

В типовых конфигурациях разработчики компании 1С иногда используют в отчетах, построенных на СКД, такую конструкцию, как "ГДЕ ЛОЖЬ". Такая конструкция говорит о том, что данные в запросе не будут получены совсем. Для чего же нужен тогда запрос?

13.02.2024    5740    KawaNoNeko    23    

23

Набор-объект для СКД по тексту или запросу

Запросы СКД Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Есть список полей в виде текста, или запрос - закидываем в набор СКД.

1 стартмани

31.01.2024    2000    2    Yashazz    0    

29

Запрос 1С copilot

Инструментарий разработчика Запросы Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Пишем на человеческом языке, что нам надо, и получаем текст запроса на языке 1С. Используются большие языковые модели (LLM GPT) от OpenAI или Яндекс на выбор.

5 стартмани

15.01.2024    6279    30    mkalimulin    25    

49

PrintWizard: поддержка представлений ЗУП в конструкторе

Инструментарий разработчика Запросы Платформа 1С v8.3 Бесплатно (free)

Одной из интересных задач, стоящих в процессе разработки, была поддержка механизма представлений в ЗУП. Но не просто возможность исполнения запросов с ними. Основная проблема была в том, чтобы с ними было удобно работать, а именно: создавать, модифицировать и отлаживать. Кратко о том, что в итоге получилось...

14.12.2023    1740    vandalsvq    7    

29

Объектная модель запроса "Схема запроса" 2

Запросы Платформа 1С v8.3 Запросы Конфигурации 1cv8 Бесплатно (free)

Далеко уже не новый тип данных "Схема запроса". Статья о том, как использовать его "попроще". Примеры создания текста запроса с нуля и изменение имеющегося запроса.

06.12.2023    5384    user1923546    26    

43

Начните уже использовать хранилище запросов

HighLoad оптимизация Запросы

Очень немногие из тех, кто занимается поддержкой MS SQL, работают с хранилищем запросов. А ведь хранилище запросов – это очень удобный, мощный и, главное, бесплатный инструмент, позволяющий быстро найти и локализовать проблему производительности и потребления ресурсов запросами. В статье расскажем о том, как использовать хранилище запросов в MS SQL и какие плюсы и минусы у него есть.

11.10.2023    16163    skovpin_sa    14    

98
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. Kolunya 6 18.11.20 11:13 Сейчас в теме
Спасибо, полезная информация!
"а что, так можно было?" )))
Плюсанул ;-)
BoBaH; gubanoff; docerman; +3 Ответить
2. VitaliyCeban 461 18.11.20 18:21 Сейчас в теме
Спасибо, век живи - век учись. Следует упомянуть что функция АВТОНОМЕРЗАПИСИ() доступна начиная с версии 8.3.13.
3. KilloN 56 18.11.20 18:23 Сейчас в теме
Зачем группировать по Организации, Контрагенту и Договору, когда Договор в себя включает и Организацию и Контрагента?
Достаточно одной группировки по договору и грузоотправителе =)
TimkoNzt; +1 Ответить
7. antonivan 161 18.11.20 19:29 Сейчас в теме
(3) Наверное, пример с договором не самый удачный) Но могут быть различные другие поля. Я столкнулся с этой задачей на другом примере, там 5 полей группировки, которые точно независимы друг от друга. Вот там точно без этого никак.
Дмитрий74Чел; +1 Ответить
4. VitaliyCeban 461 18.11.20 18:25 Сейчас в теме
(3) Наверное, чтобы не вытаскивать их из договора через точку (неявный запрос), нет?
motorsoft; ne_en; ivanov660; +3 Ответить
5. KilloN 56 18.11.20 18:28 Сейчас в теме
(4) Нет, у нас же уже есть поля Контрагент и Организация в ТаблицаТоваров, смысл обращаться к реквизитам договора?
6. VitaliyCeban 461 18.11.20 18:39 Сейчас в теме
(5) Таблицы может и не быть, могут быть случаи, когда интересует только верхняя группировка этих 4-х реквизитов, и соответствующие суммы.
8. unichkin 1559 18.11.20 23:04 Сейчас в теме
Только надо следить за тем, чтобы в таблице ВТ_ИсходнаяТаблица не было выходных NULL полей, среди тех, по которым идет соединение...
antonivan; +1 Ответить
9. antonivan 161 19.11.20 06:32 Сейчас в теме
10. user847517 1 19.11.20 11:01 Сейчас в теме
А можно просто создать процедуру "Обход результата по группировкам" и вызывать ее в цикле. Такой вариант еще в курсе "Запросы" рассматривался.
antonivan; +1 Ответить
11. antonivan 161 19.11.20 11:16 Сейчас в теме
(10) Можно и так. Через АВТОНОМЕРЗАПИСИ удобнее отлаживать будет. Представляете отладку рекурсивного вызова этой процедуры? Легко запутаться, на каком ты сейчас уровне вложенности работаешь
12. user847517 1 19.11.20 11:27 Сейчас в теме
(11)В коллекции СтрокаДеревоЗначений есть уровень(), так что у меня пока проблем отслеживания не возникало. К сожалению АВТОНОМЕРЗАПИСИ по тестить не могу, т.к. сижу на 8.2
13. ProgrammistC 60 21.11.20 11:30 Сейчас в теме
В целом интересный подход, но не для больших объемов данных. При таком подходе время на создание первой временной таблицы+ время на создание второй врем. таблицы + время на индексирование таблиц(причем бывает существенно) + время на соединение таблиц
dabu-dabu; +1 Ответить
14. antonivan 161 21.11.20 12:02 Сейчас в теме
(13) Соглашусь, что для случая, когда производительность запроса критична - нужно использовать другие подходы. Преимущество этого подхода - удобочитаемость, отлаживаемость и, как следствие, хорошая сопровождаемость кода обработки результата запроса.
15. avega67 22.11.20 22:20 Сейчас в теме
Очень красиво и изящно.
gubanoff; +1 Ответить
16. selez-a 17 24.11.20 09:09 Сейчас в теме
Спасибо за информацию. Очень полезная функция.
17. MishaD 14 24.11.20 09:29 Сейчас в теме
Что-то я торможу. А почему нельзя было просто итоги по договорам поставить ?
18. antonivan 161 24.11.20 10:20 Сейчас в теме
(17) в рамках одного договора могут быть разные грузоотправители и, соответственно, должны быть разные документы. Как уже выше писали, пример с договором не совсем удачный, потому что он включает организацию и контрагента. Так что здесь два реально независимых поля - договор и грузополучатель. Но даже для двух независимых полей этот механизм имеет смысл использовать, чтобы вложенные циклы не плодить. А если независимых полей будет больше - тем более
19. MishaD 14 24.11.20 12:16 Сейчас в теме
(18) Спасибо. Теперь понял. Красивое решение.
20. Vlad_2008 16 25.11.20 17:50 Сейчас в теме
Да интересно. Ну а нам, у кого 8.2 или нет этой функции или просто лень писать запросы руками, остается СКД : группировка по полям + вложенная группировка детальные записи, а дальше что угодно:

- хоть загружай ТЗ
- хоть выгружай в ТЗ
- хоть меняй состав полей
- все можно "набить" мышкой в конфигураторе
- кому не лень, вообще можно все собирать "на лету" без конфигуратора


... без функций, без ВТ, без индексов, без соединений, СКД все сама ...
21. digital_element 15.07.22 09:55 Сейчас в теме
Спасибо за интересное решение.

У вас опечатка в строке "ВыборкаПоНаборам = Запрос.Выполнить.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);"

- ".....Выполнить()......"
Оставьте свое сообщение