Как объединить телефон и электронную почту контактного лица в одну строку в запросе и СКД

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

При построении отчетов в конфигурациях на базе «Библиотеки стандартных подсистем» (таких как «1С:Управление торговлей 11», «1С:ERP» или «1С:Комплексная автоматизация») разработчики часто сталкиваются с задачей вывести контактные данные контрагента или контактного лица в одну строчку. Вместо желаемой компактной строки видны две или более повторяющиеся записи: в одной заполнен только телефон, а во второй — только email.

Разберем природу этой проблемы, проанализируем ошибки при сложении строк в запросе и рассмотрим несколько надежных вариантов решения задачи средствами языка запросов 1С и системы компоновки данных.

Почему контактная информация задваивает строки

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

Когда мы обращаемся напрямую к табличной части через запрос:


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

СУБД возвращает ровно столько строк, сколько записей заведено у контакта. В строке с телефонным номером поле АдресЭП будет пустым, а в строке с почтой пустым окажется НомерТелефона. Попытка просто сложить эти поля через + приведет либо к ошибке несовместимости типов, либо к результату со значениями NULL и «висячими» запятыми.

Также важно помнить об особенностях платформы при конкатенации строк в запросе:

  1. Поля неограниченной длины: складывать оператором + можно только строки ограниченной длины. Если поле имеет неограниченную длину, его необходимо явно приводить с помощью функции ВЫРАЗИТЬ(Поле КАК СТРОКА(Длина)).
  2. Поведение NULL: если хотя бы один из операндов при конкатенации равен NULL, весь итоговый результат сложения превратится в NULL. Поэтому обязательна обработка функцией ЕСТЬNULL.

Способ 1. Свертка через условные конструкции и группировку (рекомендуемый)

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

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


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

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

Способ 2. Использование нескольких левых соединений

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

Посмотрим на пример запроса:


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

Обратите внимание: если у одного контактного лица в базе зарегистрировано несколько телефонов, левое соединение размножит строки. Если существует вероятность ввода нескольких однотипных контактов, лучше использовать группировку из первого способа либо функционал СКД.

Способ 3. Решение штатными ресурсами СКД через «СоединитьСтроки»

Если разработка отчета ведется в Системе компоновки данных, писать сложные конструкции с конкатенацией строк в самом тексте запроса не обязательно. В СКД встроен агрегатный метод СоединитьСтроки, который берет на себя объединение значений.

Разберем по шагам настройку схемы компоновки данных:

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

При формировании отчета СКД автоматически свернет строки по каждому контактному лицу, исключит пустые значения и выведет все имеющиеся средства связи через запятую в одну аккуратную строку.

← На главную