При разработке отчетов в системе «1С:Предприятие» начинающие программисты часто сталкиваются с проблемой дублирования строк. Ситуация обычно выглядит так: вы выбираете данные из нескольких документов, связанных с одним объектом, но вместо аккуратного списка получаете множество повторяющихся записей. В этой статье мы подробно разберем, почему возникают дубли, как правильно настраивать связи между таблицами и как корректно работать с периодами в запросах.
Разберем типичную ошибку. Если в тексте запроса в секции ИЗ просто перечислить несколько таблиц через запятую, не указав условия связи, система выполнит так называемое «Декартово произведение» (Cross Join). Это означает, что каждая строка из первой таблицы будет объединена с каждой строкой из второй и третьей таблиц. Если у вас 10 договоров и 5 дополнительных соглашений, на выходе вы получите 50 строк.
Рассмотрим пример некорректного запроса:
ВЫБРАТЬ
ДоговорНаПроектирование.Ссылка,
ДополнительноеСоглашение.Ссылка
ИЗ
Документ.ДоговорНаПроектирование КАК ДоговорНаПроектирование,
Документ.ДополнительноеСоглашение КАК ДополнительноеСоглашение
В таком виде запрос работать не будет — он выдаст все возможные комбинации документов. Чтобы данные «схлопнулись», нам необходимо указать системе, по какому полю эти таблицы связаны. В строительстве таким полем обычно выступает ОбъектСтроительства.
Для объединения данных из разных документов необходимо использовать конструкцию СОЕДИНЕНИЕ. Однако важно выбрать правильный тип соединения. В 1С чаще всего используются Внутреннее и Левое соединения.
NULL. Это наиболее подходящий вариант для отчетов по объектам строительства, так как по объекту всегда есть основной договор, а дополнительные соглашения или договоры субподряда могут отсутствовать.Проанализируем исправленный вариант запроса с использованием левого соединения:
ВЫБРАТЬ
Договор.Ссылка КАК Договор,
ДопСоглашение.Ссылка КАК ДопСоглашение,
ЕСТЬNULL(ДопСоглашение.Сумма, 0) КАК СуммаДоп
ИЗ
Документ.ДоговорНаПроектирование КАК Договор
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ДополнительноеСоглашение КАК ДопСоглашение
ПО Договор.ОбъектСтроительства = ДопСоглашение.ОбъектСтроительства
Важный момент: Обратите внимание на условие ПО. Всегда старайтесь соединять таблицы по ссылочным полям (Ссылка), а не по строковым представлениям или кодам. Сравнение ссылок работает значительно быстрее и надежнее.
Если после настройки связей дубли все равно остаются, проанализируем структуру данных. Скорее всего, одному договору соответствует несколько записей в подчиненной таблице (например, три доп. соглашения к одному договору). В этом случае в отчете действительно должно быть три строки, если вы выводите информацию о доп. соглашениях.
Если же вам нужно получить общую сумму по объекту в одной строке, воспользуемся механизмом группировки:
СГРУППИРОВАТЬ ПО.СУММА().МАКСИМУМ() или включаем их в список группировки.Пример группировки:
ВЫБРАТЬ
Договор.ОбъектСтроительства КАК Объект,
СУММА(Договор.СуммаДоговора) КАК СуммаОсновная,
СУММА(ЕСТЬNULL(ДопСоглашение.Сумма, 0)) КАК СуммаДопов
ИЗ
Документ.ДоговорНаПроектирование КАК Договор
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ДополнительноеСоглашение КАК ДопСоглашение
ПО Договор.Ссылка = ДопСоглашение.ДоговорОснование
СГРУППИРОВАТЬ ПО
Договор.ОбъектСтроительства
Часто отчет не выводит данные или выводит лишние из-за неправильной работы с датами. В 1С тип Дата включает время. Если вы передадите в параметр дату «01.08.2023», система воспримет это как начало дня — «01.08.2023 00:00:00». Документы, созданные в течение этого дня, не попадут в выборку МЕЖДУ.
Для корректной фильтрации разберем использование функции КОНЕЦПЕРИОДА:
ГДЕ
Договор.Дата МЕЖДУ &ДатаНачала И КОНЕЦПЕРИОДА(&ДатаОкончания, ДЕНЬ)
Функция КОНЕЦПЕРИОДА установит время на 23:59:59, что позволит захватить все документы за последний день периода.
При программной установке параметров в модуле формы, убедитесь, что вы обращаетесь к реквизитам правильно. Если параметры определены на форме отчета, используйте следующий подход:
Процедура СформироватьОтчет()
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ... ГДЕ Дата МЕЖДУ &НачДата И &КонДата";
// Установка параметров
Запрос.УстановитьПараметр("НачДата", Объект.ДатаНачала);
Запрос.УстановитьПараметр("КонДата", КонецДня(Объект.ДатаОкончания));
Результат = Запрос.Выполнить();
КонецПроцедуры
Если вы запутались в соединениях и не понимаете, какая таблица «множит» строки, воспользуйтесь методом исключения:
ЛЕВОЕ СОЕДИНЕНИЕ).ПО для этой таблицы. Возможно, там не хватает дополнительного условия (например, связи не только по объекту, но и по контрагенту).И помните: для разработки сложных отчетов в современной 1С лучше всего использовать СКД (Систему компоновки данных). Она берет на себя большинство задач по группировке, расчету итогов и корректному выводу данных без дублей, предоставляя пользователю гибкие настройки внешнего вида отчета без переписывания кода запроса.