При разработке отчетов и обработок в 1С часто возникает задача получить общую сумму по нескольким проводкам одного документа. Например, когда в документе поступления присутствуют проводки по дебету счета 08.03 («Строительство объектов основных средств») и дебету счета 19.04 («НДС по приобретенным материально-производственным запасам») в корреспонденции со счетом 60.01 («Расчеты с поставщиками и подрядчиками»), и требуется получить их общую сумму по кредиту. Разберем по шагам, как правильно объединить такие строки в запросе, почему простая группировка или использование временных таблиц могут приводить к размножению строк, и как этого избежать.
Рассмотрим исходный запрос к виртуальной таблице регистра бухгалтерии, с которого начинается проблема:
ВЫБРАТЬ
ХозрасчетныйДвиженияССубконто.Регистратор,
ХозрасчетныйДвиженияССубконто.СчетКт,
ХозрасчетныйДвиженияССубконто.СчетДт,
ХозрасчетныйДвиженияССубконто.СубконтоДт1,
ХозрасчетныйДвиженияССубконто.СубконтоДт2,
ХозрасчетныйДвиженияССубконто.СубконтоДт3,
ХозрасчетныйДвиженияССубконто.Сумма КАК Сумма
ИЗ
РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(, , Регистратор = &Регистратор, , ) КАК ХозрасчетныйДвиженияССубконто
При выполнении такого запроса система возвращает две отдельные записи. Попытки применить агрегатную функцию СУММА или соединить временные таблицы часто приводят к непредвиденным результатам.
Проанализируем ситуацию, возникающую при попытке сложения строк регистра бухгалтерии:
СГРУППИРОВАТЬ ПО в языке запросов 1С объединяет строки только при полном совпадении всех неагрегированных полей выборки. Проводка по счету 08.03 и проводка по счету 19.04 имеют разные значения в поле СчетДт. Кроме того, у счетов 08.03 и 19.04 принципиально различается состав субконто: для 08.03 это «Объекты строительства» и «Статьи затрат», а для 19.04 — «Контрагенты» и «Счета-фактуры полученные». Пока эти поля присутствуют в секции ВЫБРАТЬ без агрегации, строки никогда не схлопнутся в одну.Регистратор без предварительной группировки приводит к эффекту $M \times N$. Если в документе было несколько строк по счету 08 или по счету 19, строки взаимно перемножаются, в результате чего результирующая таблица разрастается.Если конечная цель заключается в том, чтобы получить общую сумму взаиморасчетов по кредиту счета 60.01 в рамках регистратора, нам необходимо исключить из списка выборки и секции группировки все поля, которые уникальны для каждой проводки (в частности, СчетДт и СубконтоДт1...3).
Посмотрим на пример правильного формирования запроса:
ВЫБРАТЬ
Хозрасчетный.Регистратор КАК Регистратор,
Хозрасчетный.СчетКт КАК СчетКт,
Хозрасчетный.СубконтоКт1 КАК Контрагент,
Хозрасчетный.СубконтоКт2 КАК Договор,
СУММА(Хозрасчетный.Сумма) КАК ОбщаяСумма
ИЗ
РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
ГДЕ
Хозрасчетный.Регистратор = &Регистратор
И Хозрасчетный.СчетКт В ИЕРАРХИИ (&Счет60)
СГРУППИРОВАТЬ ПО
Хозрасчетный.Регистратор,
Хозрасчетный.СчетКт,
Хозрасчетный.СубконтоКт1,
Хозрасчетный.СубконтоКт2
В данном случае все строки документа, относящиеся к одному и тому же контрагенту и договору по кредиту, корректно просуммируются оператором СУММА в одну строку.
Рассмотрим случай, когда в одной результирующей строке документа требуется одновременно видеть и сумму затрат (08.03), и сумму НДС (19.04), и их общую сумму. Для этого применим конструкцию ВЫБОР КОГДА внутри агрегатной функции СУММА:
ВЫБРАТЬ
Хозрасчетный.Регистратор КАК Регистратор,
Хозрасчетный.СчетКт КАК СчетКт,
СУММА(ВЫБОР
КОГДА Хозрасчетный.СчетДт = &Счет0803
ТОГДА Хозрасчетный.Сумма
ИНАЧЕ 0
КОНЕЦ) КАК СуммаКапВложений,
СУММА(ВЫБОР
КОГДА Хозрасчетный.СчетДт = &Счет1904
ТОГДА Хозрасчетный.Сумма
ИНАЧЕ 0
КОНЕЦ) КАК СуммаНДС,
СУММА(Хозрасчетный.Сумма) КАК СуммаВсего
ИЗ
РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный
ГДЕ
Хозрасчетный.Регистратор = &Регистратор
И Хозрасчетный.СчетДт В (&СписокСчетовДт)
СГРУППИРОВАТЬ ПО
Хозрасчетный.Регистратор,
Хозрасчетный.СчетКт
Такой подход позволяет сохранить прозрачность расчетов: строки схлопываются до уровня документа и кредитового счета, а суммы по разным дебетовым счетам разносятся по соответствующим колонкам без дублирования.
Если логика требует использования временных таблиц (например, для сложной предварительной обработки), разберем, как избежать размножения записей:
ЛЕВОЕ СОЕДИНЕНИЕ или ПОЛНОЕ СОЕДИНЕНИЕ по полю Регистратор, каждая из связываемых таблиц должна быть предварительно сгруппирована. Отношение записей должно строго составлять 1:1, иначе возникнет декартово произведение.СОЕДИНЕНИЕ безопаснее поместить разнородные строки в единый поток через ОБЪЕДИНИТЬ ВСЕ, после чего наложить общую группировку:
ВЫБРАТЬ
ВТ_Проводки.Регистратор КАК Регистратор,
СУММА(ВТ_Проводки.Сумма) КАК ИтогоСумма
ИЗ
(ВЫБРАТЬ
Движения.Регистратор КАК Регистратор,
Движения.Сумма КАК Сумма
ИЗ
РегистрБухгалтерии.Хозрасчетный КАК Движения
ГДЕ
Движения.Регистратор = &Регистратор
И Движения.СчетДт = &Счет0803
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Движения.Регистратор КАК Регистратор,
Движения.Сумма КАК Сумма
ИЗ
РегистрБухгалтерии.Хозрасчетный КАК Движения
ГДЕ
Движения.Регистратор = &Регистратор
И Движения.СчетДт = &Счет1904) КАК ВТ_Проводки
СГРУППИРОВАТЬ ПО
ВТ_Проводки.Регистратор
Обратим внимание на важную архитектурную деталь платформы 1С: виртуальная таблица ДвиженияССубконто выполняет ресурсоемкие соединения с таблицами значений субконто. Если для решения задачи аналитика дебета (СубконтоДт1...3) в итоговой выборке не нужна, обращаться к виртуальной таблице ДвиженияССубконто не рекомендуется. Для получения сумм проводок конкретного регистратора быстрее и эффективнее использовать реальную физическую таблицу РегистрБухгалтерии.Хозрасчетный с отбором по полю Регистратор.