Как в одном запросе 1С получить несколько разных видов контактной информации (телефонов)?

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

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

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

Рассмотрим классический способ, когда мы выбираем список объектов и последовательно присоединяем к нему данные контактной информации с помощью конструкции ЛЕВОЕ СОЕДИНЕНИЕ для каждого нужного вида.

Проанализируем пример кода на языке 1С:


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

Запрос.УстановитьПараметр("МассивКонтрагентов", МассивКонтрагентов);
Запрос.УстановитьПараметр("ТипКИТелефон", Перечисления.ТипыКонтактнойИнформации.Телефон);
Запрос.УстановитьПараметр("ВидКИРабочийТелефон", Справочники.ВидыКонтактнойИнформации.ТелефонКонтрагента);
Запрос.УстановитьПараметр("ВидКИМобильныйТелефон", ВидКИМобильныйТелефон);

РезультатЗапроса = Запрос.Выполнить();

Обратим внимание на важные детали в этом примере:

  1. Использование функции ЕСТЬNULL позволяет подставить пустую строку, если у контрагента не заполнен соответствующий вид телефона.
  2. Условия по виду и типу контактной информации помещены непосредственно в секцию соединения ПО, а не в блок ГДЕ, благодаря чему контрагенты без телефонов не отсекаются из результирующей выборки.

Вариант 2. Свертка через условные конструкции ВЫБОР и группировку (оптимальный подход)

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

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


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

Преимущества данного метода:

  1. Таблица контактной информации читается СУБД всего один раз, что существенно снижает нагрузку при больших объемах данных.
  2. Агрегатная функция МАКСИМУМ гарантирует получение ровно одной строки на каждый объект, исключая случайное размножение строк.

Как получить контактную информацию по разнородным объектам (Контрагенты и Физлица)

Иногда требуется получить телефоны одновременно для объектов разных типов — например, для организаций, физических лиц и контрагентов. В этом случае сформируем единую временную таблицу ссылок с помощью оператора ОБЪЕДИНИТЬ ВСЕ.

Разберем по шагам построение такого запроса:


ВЫБРАТЬ
    Контрагенты.Ссылка КАК Объект
ПОМЕСТИТЬ ВТ_ОбъектыКИ
ИЗ
    Справочник.Контрагенты КАК Контрагенты
ГДЕ
    Контрагенты.Ссылка В(&МассивКонтрагентов)

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    ФизЛица.Ссылка КАК Объект
ИЗ
    Справочник.ФизическиеЛица КАК ФизЛица
ГДЕ
    ФизЛица.Ссылка В(&МассивФизЛиц)
;

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

Поместив ссылки во временную таблицу ВТ_ОбъектыКИ, мы получаем универсальный набор данных, к которому далее присоединяется контактная информация вне зависимости от конкретного типа справочника.

Особенности работы с контактной информацией в современных конфигурациях (БСП)

Выясним важное архитектурное отличие современных типовых конфигураций (таких как ERP 2, КА 2, УТ 11, БП 3.0, ЗУП 3.1):

  1. Табличные части вместо регистра: В типовых конфигурациях на базе БСП контактная информация чаще всего хранится не в регистре сведений, а в одноименных табличных частях справочников — например, Справочник.Контрагенты.КонтактнаяИнформация. При составлении запросов в таких конфигурациях источником данных служит сама табличная часть объекта.
  2. Прямое обращение к предопределенным значениям: Чтобы не передавать виды контактной информации через параметры запроса, можно использовать прямое обращение: КИ.Вид = ЗНАЧЕНИЕ(Справочник.ВидыКонтактнойИнформации.ТелефонКонтрагента).
  3. Программный интерфейс (API): Если данные требуется прочитать в коде модуля, рекомендуется использовать функции общего модуля УправлениеКонтактнойИнформацией, которые берут на себя работу с форматами хранения и парсингом номеров.
← На главную