Как убрать дублирующиеся строки в запросе 1С при получении контактной информации?

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

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

В этой статье мы подробно разберем, почему возникает такая ситуация, и рассмотрим несколько эффективных способов получения данных в одну строку без дублей.

Почему возникают дубли и почему не помогает ВЫБРАТЬ РАЗЛИЧНЫЕ?

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

Если у контактного лица заполнено два вида информации (телефон и почта), база данных честно возвращает две строки. Использование ключевого слова РАЗЛИЧНЫЕ (SQL DISTINCT) в данном случае не помогает по следующим причинам:

  1. Различие в значениях полей: В одной строке в поле НомерТелефона стоит значение, а в поле АдресЭП — NULL. В другой строке — наоборот. Для системы это абсолютно разные наборы данных, и она не может их «схлопнуть».
  2. Скрытые поля: Если в запрос попали системные поля, такие как НомерСтроки табличной части, то строки всегда будут уникальными для СУБД, так как индексы строк различаются.

Рассмотрим способы корректного решения этой задачи.

Способ 1. Использование нескольких соединений с фильтрацией

Этот метод считается классическим и наиболее понятным. Вместо одного общего соединения с таблицей контактной информации, мы выполним несколько соединений — по одному для каждого нужного нам вида данных (например, отдельно для телефона и отдельно для почты).

Разберем по шагам: мы присоединяем таблицу контактной информации дважды, но в условии связи ПО жестко ограничиваем тип выбираемых данных. Посмотрим на пример кода:


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

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

Способ 2. Группировка данных и агрегатные функции

Если видов контактной информации много, плодить десятки соединений может быть неудобно. В этом случае мы можем использовать механизм группировки. Идея заключается в том, чтобы сгруппировать результат по ссылке партнера, а для полей контактов использовать агрегатную функцию МАКСИМУМ.

Проанализируем, как это работает: так как для каждого вида информации в строке будет либо значение, либо NULL, функция МАКСИМУМ выберет существующее строковое значение, проигнорировав пустые записи.


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

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

Способ 3. Обращение к регистру сведений (для типовых конфигураций)

В современных конфигурациях, построенных на базе Библиотеки Стандартных Подсистем (БСП), таких как ERP, УТ 11 или Бухгалтерия 3.0, контактная информация дублируется в регистре сведений КонтактнаяИнформация. Работа с регистром часто оказывается более производительной, чем с табличными частями.

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

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

При работе с большими объемами данных (тысячи контрагентов), выполнение множественных соединений или сложных группировок может замедлить отчет. В таких ситуациях рекомендуется:

  1. Использовать временные таблицы: Сначала выберите список нужных вам партнеров во временную таблицу, а затем присоединяйте к ней контакты.
  2. Функция ЕСТЬNULL: Всегда обрабатывайте результат соединения функций ЕСТЬNULL(Поле, ""). Это предотвратит появление пустых значений в отчете и сделает данные более читаемыми.
  3. Программная обработка: Если у одного контакта может быть 3-4 телефона, которые нужно вывести через запятую, лучше сделать это не в запросе, а при выводе данных в Схеме Компоновки Данных (СКД), используя вычисляемые поля или ресурсы с функцией СоединитьСтроки().

Подведем итог: чтобы убрать дубли, мы должны четко указать системе, какие именно данные мы хотим видеть в каждой конкретной колонке, используя либо условия в параметрах связи, либо группировку с агрегацией. Это обеспечит чистоту данных и корректный вид вашего отчета.

← На главную