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