Как вывести юридический и фактический адреса контрагента в одну строку запроса 1С?

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

В процессе разработки отчетов в системе 1С:Предприятие, особенно в таких конфигурациях, как УПП (Управление производственным предприятием), программисты часто сталкиваются с особенностью хранения контактной информации. Юридические, фактические и почтовые адреса хранятся в регистре сведений КонтактнаяИнформация в виде отдельных записей для каждого вида. Если попытаться выбрать их простым запросом, мы получим несколько строк для одного контрагента, что неудобно для выгрузки в Excel или формирования печатных форм.

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

Причина проблемы: почему стандартный запрос не работает

Проанализируем ситуацию, представленную в вопросе автора. Когда мы пишем конструкцию ВЫБОР КОГДА КонтактнаяИнформация.Вид = &ВидАдреса ТОГДА ... внутри общего запроса к регистру, система все равно перебирает каждую запись регистра. Если у контрагента есть два адреса, запрос вернет две строки: в первой будет заполнен юридический адрес (а фактический будет пустым), а во второй — наоборот. Наша задача — объединить эти данные в одну горизонтальную запись.

Метод 1: Множественные левые соединения

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

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

Рассмотрим пример готового кода:


ВЫБРАТЬ
    Контрагенты.Наименование КАК Наименование,
    Контрагенты.ИНН КАК ИНН,
    ЕСТЬNULL(АдресЮр.Представление, "") КАК ЮрАдрес,
    ЕСТЬNULL(АдресФакт.Представление, "") КАК ФактАдрес
ИЗ
    Справочник.Контрагенты КАК Контрагенты
    
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК АдресЮр
        ПО Контрагенты.Ссылка = АдресЮр.Объект
        И АдресЮр.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ЮрАдресКонтрагента)
        
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК АдресФакт
        ПО Контрагенты.Ссылка = АдресФакт.Объект
        И АдресФакт.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ФактАдресКонтрагента)

Важный нюанс: Обратите внимание, что условие по виду контактной информации (АдресЮр.Вид = ...) вынесено именно в секцию ПО (условие связи), а не в секцию ГДЕ. Если вы поместите это условие в ГДЕ, левое соединение фактически превратится во внутреннее, и контрагенты, у которых не заполнен хотя бы один из адресов, просто исчезнут из результата запроса.

Метод 2: Агрегация через группировку (МАКСИМУМ)

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

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


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

Этот метод считается более профессиональным и «чистым» с точки зрения SQL-оптимизатора, так как требует меньше ресурсов для сканирования таблиц.

Метод 3: Использование возможностей СКД

Если вы разрабатываете отчет на базе Системы компоновки данных, вам не обязательно прописывать сложные соединения вручную в тексте запроса. Посмотрим, как это упростить:

  1. Механизм характеристик: В схеме компоновки данных на закладке «Объекты» можно настроить характеристики для справочника Контрагенты. Указав в качестве источника характеристик регистр КонтактнаяИнформация, вы получите виртуальные поля (Юр. адрес, Телефон и т.д.) прямо в списке доступных полей компоновки. Система сама сформирует оптимальный запрос.
  2. Функция СоединитьСтроки(): Если у одного контрагента может быть несколько телефонов или адресов одного вида, и их нужно вывести через запятую, используйте в вычисляемых полях или ресурсах функцию: СоединитьСтроки(Массив(Представление), "; ").

Рекомендации по оптимизации и типичные ошибки

Проанализируем несколько важных моментов, которые помогут вам избежать ошибок:

1. Использование ЕСТЬNULL: Как было отмечено в сообщении 5 на форуме, использование ЕСТЬNULL(Поле, "") критически важно. В языке запросов 1С любая операция со значением NULL (например, сложение строк) приведет к тому, что весь результат станет NULL. Всегда приводите пустые значения к пустой строке.

2. Типы объектов: В регистре КонтактнаяИнформация поле Объект имеет составной тип. Для ускорения запроса в больших базах данных (например, в крупных внедрениях УПП) полезно добавить условие по типу ссылки: И КИ.Объект ССЫЛКА Справочник.Контрагенты.

3. Представление vs ЗначенияПолей: Помните, что поле Представление — это готовая строка адреса. Если же вам нужно выгрузить адрес «по частям» (город, улица, дом отдельно), вам придется работать с полем ЗначенияПолей (которое содержит XML или JSON) и использовать программные функции разбора адреса из БСП, так как запрос 1С не умеет парсить такие данные самостоятельно.

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

← На главную