Как избежать дублирования записей при выборке дополнительных реквизитов и контактной информации в 1С

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей IT и автоматизация бизнеса
← На главную

При работе с запросами в системе 1С:Предприятие программисты часто сталкиваются с ситуацией, когда результат выборки содержит гораздо больше строк, чем ожидалось. Особенно ярко это проявляется при попытке получить данные из справочника (например, Партнеры или Контрагенты) одновременно с его табличными частями: ДополнительныеРеквизиты и КонтактнаяИнформация. В этой статье мы подробно разберем, почему это происходит и как правильно строить запросы, чтобы данные не «задваивались».

Почему строки в запросе «размножаются»?

Разберем ситуацию на примере. Представим, что у одного партнера в базе данных есть 2 записи в табличной части контактной информации (телефон и адрес) и 2 записи в дополнительных реквизитах (экспедитор и курьер). Когда мы выполняем ЛЕВОЕ СОЕДИНЕНИЕ основной таблицы со всеми этими табличными частями одновременно по полю Ссылка, СУБД выполняет математическое перемножение строк (декартово произведение).

Проанализируем механику: для каждой строки из таблицы контактов система найдет все соответствующие строки из таблицы доп. реквизитов. В итоге вместо 2 или 4 строк мы получим 4 строки (2 контакта * 2 реквизита), где данные будут перемешаны. Это не ошибка платформы 1С, а базовая логика работы SQL-запросов. Выход из этой ситуации — правильное структурирование запроса.

Решение №1: Использование фильтрации в условии соединения

Если нам нужно получить конкретные значения (например, только «Адрес доставки» и только реквизит «Экспедитор»), мы должны ограничить выборку еще на этапе соединения таблиц. Рассмотрим, как изменить стандартный запрос:


ВЫБРАТЬ
    Партнеры.Наименование КАК Наименование,
    ПартнерыКонтактнаяИнформация.Представление КАК АдресДоставки,
    ПартнерыДополнительныеРеквизиты.Значение КАК Экспедитор
ИЗ
    Справочник.Партнеры КАК Партнеры
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Партнеры.КонтактнаяИнформация КАК ПартнерыКонтактнаяИнформация
        ПО Партнеры.Ссылка = ПартнерыКонтактнаяИнформация.Ссылка
            И ПартнерыКонтактнаяИнформация.Вид = &ВидАдресДоставки
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Партнеры.ДополнительныеРеквизиты КАК ПартнерыДополнительныеРеквизиты
        ПО Партнеры.Ссылка = ПартнерыДополнительныеРеквизиты.Ссылка
            И ПартнерыДополнительныеРеквизиты.Свойство = &СвойствоЭкспедитор

В данном примере мы добавили условия И ПартнерыКонтактнаяИнформация.Вид = &ВидАдресДоставки непосредственно в секцию ПО. Это критически важно: система сначала отфильтрует строки в подчиненных таблицах и только потом присоединит их к основной таблице. Если для каждого партнера существует только один «Адрес доставки» и один «Экспедитор», дублей не будет.

Решение №2: Использование временных таблиц (ВТ)

Когда данных много или логика выборки сложная, использование временных таблиц является «золотым стандартом» разработки на 1С. Это делает запрос читаемым и позволяет оптимизатору SQL лучше отрабатывать план выполнения. Разберем этот метод по шагам.

Шаг 1. Выбираем контактную информацию во временную таблицу:


ВЫБРАТЬ
    ПартнерыКИ.Ссылка КАК Партнер,
    ПартнерыКИ.Представление КАК Адрес
ПОМЕСТИТЬ ВТ_Контакты
ИЗ
    Справочник.Партнеры.КонтактнаяИнформация КАК ПартнерыКИ
ГДЕ
    ПартнерыКИ.Вид = &ВидАдрес
;

Шаг 2. Выбираем дополнительные реквизиты во временную таблицу:


ВЫБРАТЬ
    ПартнерыДоп.Ссылка КАК Партнер,
    ПартнерыДоп.Значение КАК ЗначениеЭкспедитор
ПОМЕСТИТЬ ВТ_ДопРеквизиты
ИЗ
    Справочник.Партнеры.ДополнительныеРеквизиты КАК ПартнерыДоп
ГДЕ
    ПартнерыДоп.Свойство = &СвойствоЭкспедитор
;

Шаг 3. Соединяем все данные в итоговом запросе:


ВЫБРАТЬ
    Партнеры.Ссылка КАК Ссылка,
    Партнеры.Наименование КАК Наименование,
    ЕСТЬNULL(ВТ_Контакты.Адрес, "") КАК Адрес,
    ЕСТЬNULL(ВТ_ДопРеквизиты.ЗначениеЭкспедитор, "Не указан") КАК Экспедитор
ИЗ
    Справочник.Партнеры КАК Партнеры
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Контакты КАК ВТ_Контакты
        ПО Партнеры.Ссылка = ВТ_Контакты.Партнер
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ДопРеквизиты КАК ВТ_ДопРеквизиты
        ПО Партнеры.Ссылка = ВТ_ДопРеквизиты.Партнер

Этот подход гарантирует, что мы работаем с уже подготовленными и «плоскими» наборами данных, что исключает неконтролируемое размножение строк.

Решение №3: Разворачивание строк в колонки (Pivoting)

Иногда стоит задача вывести несколько разных дополнительных реквизитов в одну строку для одного контрагента. В этом случае мы можем использовать агрегатные функции с условием. Проанализируем пример, где нам нужно вывести сразу и Экспедитора, и Курьера в разные колонки:


ВЫБРАТЬ
    ДопРеквизиты.Ссылка КАК Партнер,
    МАКСИМУМ(ВЫБОР
            КОГДА ДопРеквизиты.Свойство = &СвойствоЭкспедитор
                ТОГДА ДопРеквизиты.Значение
        КОНЕЦ) КАК Экспедитор,
    МАКСИМУМ(ВЫБОР
            КОГДА ДопРеквизиты.Свойство = &СвойствоКурьер
                ТОГДА ДопРеквизиты.Значение
        КОНЕЦ) КАК Курьер
ПОМЕСТИТЬ ВТ_РазвернутыеРеквизиты
ИЗ
    Справочник.Партнеры.ДополнительныеРеквизиты КАК ДопРеквизиты
ГДЕ
    ДопРеквизиты.Свойство В (&СписокНужныхСвойств)
СГРУППИРОВАТЬ ПО
    ДопРеквизиты.Ссылка

Здесь мы используем СГРУППИРОВАТЬ ПО, чтобы для каждой ссылки партнера осталась ровно одна строка, а значения распределились по соответствующим колонкам с помощью конструкции ВЫБОР. Это один из самых эффективных способов построения сложных отчетов.

Рекомендации по оптимизации

  1. Индексация: Если вы используете временные таблицы, всегда индексируйте их по полям связи (например, ИНДЕКСИРОВАТЬ ПО Партнер). Это значительно ускорит работу ЛЕВОГО СОЕДИНЕНИЯ в финальном запросе.
  2. Система компоновки данных (СКД): Если вашей целью является создание отчета, рассмотрите возможность использования СКД. В СКД можно создать отдельные наборы данных (запросы) для партнеров, контактов и свойств, а связи между ними настроить на вкладке «Связи наборов данных». Платформа сама оптимизирует выполнение и корректно выведет данные без дублей в итоговой группировке.
  3. Библиотека стандартных подсистем (БСП): Помните, что в типовых конфигурациях (УТ 11, ERP) контактная информация может храниться не только в табличных частях, но и в регистре сведений. Для получения актуальных данных рекомендуется использовать программный интерфейс БСП, например, функции модуля УправлениеКонтактнойИнформацией.

Подводя итог, можно сказать, что «задвоение» записей — это сигнал о том, что структура запроса не учитывает множественность подчиненных данных. Применяя временные таблицы и группировки, мы превращаем хаотичный набор строк в структурированную и полезную информацию.

← На главную