При формировании сводных отчетов и выборок в 1С часто возникает типовая задача: сгруппировать документы по определенному признаку (организации, контрагенту, источнику или дополнительному реквизиту), посчитать число документов в каждой группе и вычислить общую сумму. Разберем по шагам, как правильно составить такой запрос как для простых реквизитов шапки, так и для табличных частей с дополнительными реквизитами.
Рассмотрим стандартный сценарий, когда поле группировки находится непосредственно в реквизитах документа (например, Организация или ИсточникПривлечения). Для получения корректного результата используем агрегатные функции СУММА и КОЛИЧЕСТВО с модификатором РАЗЛИЧНЫЕ.
Посмотрим на пример запроса для документа Заказ покупателя:
ВЫБРАТЬ
ЗаказПокупателя.Организация КАК Организация,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ЗаказПокупателя.Ссылка) КАК КоличествоДокументов,
СУММА(ЗаказПокупателя.СуммаДокумента) КАК СуммаДокументов
ИЗ
Документ.ЗаказПокупателя КАК ЗаказПокупателя
ГДЕ
ЗаказПокупателя.Проведен = ИСТИНА
И ЗаказПокупателя.Дата МЕЖДУ &НачДата И &КонДата
СГРУППИРОВАТЬ ПО
ЗаказПокупателя.Организация
Разберем важные особенности этой конструкции:
ЗаказПокупателя.Организация), обязательно должны быть перечислены в секции СГРУППИРОВАТЬ ПО.КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ЗаказПокупателя.Ссылка) гарантирует подсчет уникальных документов. Если не указать РАЗЛИЧНЫЕ для поля группировки шапки, подсчитается общее количество записей, однако при наличии соединений с другими таблицами результат без РАЗЛИЧНЫЕ может быть искажен.СУММА(ЗаказПокупателя.СуммаДокумента) суммирует значения реквизита в рамках каждой сформированной группы.Сложности возникают, когда признак для группировки хранится не в шапке документа, а в подчиненной табличной части ДополнительныеРеквизиты (механизм БСП). При попытке обратиться к табличной части через точку в секции соединения возникает ошибка платформы: В условиях соединения запроса не допускается обращение к табличным частям.
Проанализируем основные причины этой ошибки и некорректных итогов:
ПО Документ.ДополнительныеРеквизиты.Значение = ... недопустима, так как табличная часть — это отдельная физическая таблица СУБД.Ссылка.СГРУППИРОВАТЬ ПО указать ссылку на документ, платформа вернет список документов, а не свод по значениям реквизита.Рассмотрим правильный вариант запроса, где мы соединяем документ и его табличную часть по ссылке и группируем результат по значению дополнительного свойства:
ВЫБРАТЬ
ДопРеквизиты.Значение КАК ЗначениеРеквизита,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ЗаказКлиента.Ссылка) КАК КоличествоДокументов,
СУММА(ЗаказКлиента.СуммаДокумента) КАК СуммаДокументов
ИЗ
Документ.ЗаказКлиента.ДополнительныеРеквизиты КАК ДопРеквизиты
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента КАК ЗаказКлиента
ПО ДопРеквизиты.Ссылка = ЗаказКлиента.Ссылка
ГДЕ
ДопРеквизиты.Свойство = &Свойство
И ЗаказКлиента.Дата МЕЖДУ &НачДата И &КонДата
И ЗаказКлиента.Проведен = ИСТИНА
СГРУППИРОВАТЬ ПО
ДопРеквизиты.Значение
Поскольку поле Ссылка в табличной части само по себе содержит ссылку на документ-владелец, мы можем обратиться к реквизитам шапки через точку от поля Ссылка. Это позволяет упростить текст запроса и избежать явной конструкции соединения:
ВЫБРАТЬ
ДопРеквизиты.Значение КАК ЗначениеРеквизита,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ДопРеквизиты.Ссылка) КАК КоличествоДокументов,
СУММА(ДопРеквизиты.Ссылка.СуммаДокумента) КАК СуммаДокументов
ИЗ
Документ.ЗаказКлиента.ДополнительныеРеквизиты КАК ДопРеквизиты
ГДЕ
ДопРеквизиты.Свойство = &Свойство
И ДопРеквизиты.Ссылка.Дата МЕЖДУ &НачДата И &КонДата
И ДопРеквизиты.Ссылка.Проведен = ИСТИНА
СГРУППИРОВАТЬ ПО
ДопРеквизиты.Значение
Если в отчет требуется включить также и те документы, у которых дополнительный реквизит не заполнен вовсе, строим запрос от таблицы документов с помощью ЛЕВОЕ СОЕДИНЕНИЕ:
ВЫБРАТЬ
ЕСТЬNULL(ДопРеквизиты.Значение, "Не заполнено") КАК ЗначениеРеквизита,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ЗаказКлиента.Ссылка) КАК КоличествоДокументов,
СУММА(ЗаказКлиента.СуммаДокумента) КАК СуммаДокументов
ИЗ
Документ.ЗаказКлиента КАК ЗаказКлиента
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента.ДополнительныеРеквизиты КАК ДопРеквизиты
ПО ЗаказКлиента.Ссылка = ДопРеквизиты.Ссылка
И ДопРеквизиты.Свойство = &Свойство
ГДЕ
ЗаказКлиента.Дата МЕЖДУ &НачДата И &КонДата
И ЗаказКлиента.Проведен = ИСТИНА
СГРУППИРОВАТЬ ПО
ЕСТЬNULL(ДопРеквизиты.Значение, "Не заполнено")
Обратите внимание: условие по свойству ДопРеквизиты.Свойство = &Свойство в случае левого соединения обязательно помещается в секцию ПО, а не в ГДЕ. Если указать его в ГДЕ, левое соединение превратится во внутреннее, и документы без заполненного свойства отсекутся.