При разработке отчетов или обработок в конфигурациях, построенных на базе современных типовых решений (таких как 1С:Розница 2.2 или 1С:Управление торговлей 11), часто возникает задача вывести данные о физических лицах в одну таблицу. Сложность заключается в том, что контактная информация (адреса, телефоны, email) и дополнительные реквизиты хранятся не в основных полях справочника, а в подчиненных табличных частях или регистрах. Рассмотрим подробно несколько способов решения этой задачи, от простых запросов до использования встроенных функций Библиотеки стандартных подсистем (БСП).
Это самый очевидный подход, который часто выбирают начинающие разработчики. Суть метода заключается в том, что мы берем основную таблицу справочника ФизическиеЛица и последовательно присоединяем к ней табличную часть КонтактнаяИнформация для каждого нужного нам вида данных (отдельно для телефона, отдельно для адреса и т.д.).
Рассмотрим пример запроса, в котором мы выбираем ссылку на физлицо, его адрес и телефон:
ВЫБРАТЬ
ФизическиеЛица.Ссылка КАК ФизЛицо,
ФизическиеЛицаКонтактнаяИнформацияАдрес.Представление КАК Адрес,
ФизическиеЛицаКонтактнаяИнформацияТелефон.Представление КАК Телефон
ИЗ
Справочник.ФизическиеЛица КАК ФизическиеЛица
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ФизическиеЛица.КонтактнаяИнформация КАК ФизическиеЛицаКонтактнаяИнформацияАдрес
ПО ФизическиеЛица.Ссылка = ФизическиеЛицаКонтактнаяИнформацияАдрес.Ссылка
И (ФизическиеЛицаКонтактнаяИнформацияАдрес.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Адрес))
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ФизическиеЛица.КонтактнаяИнформация КАК ФизическиеЛицаКонтактнаяИнформацияТелефон
ПО ФизическиеЛица.Ссылка = ФизическиеЛицаКонтактнаяИнформацияТелефон.Ссылка
И (ФизическиеЛицаКонтактнаяИнформацияТелефон.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Телефон))
Важный нюанс: при таком подходе необходимо четко ограничивать условие соединения не только по ссылке, но и по типу или виду контактной информации. Если у одного физлица будет два телефона, этот запрос "размножит" строки в итоговом результате. Чтобы этого избежать, часто добавляют дополнительные условия на конкретный Вид (например, "Рабочий телефон" или "Адрес проживания").
Если видов контактной информации много (например, более 5–7), использование большого количества левых соединений в одном пакете может негативно сказаться на производительности. Проанализируем вариант, когда данные сначала подготавливаются во временных таблицах, а затем собираются воедино.
Разберем по шагам, как это реализовать:
Пример кода с использованием временных таблиц:
ВЫБРАТЬ
КонтактнаяИнформация.Ссылка КАК физЛицо,
ЕСТЬNULL(КонтактнаяИнформация.Представление, "") КАК Телефон
ПОМЕСТИТЬ времТабТелефон
ИЗ
Справочник.ФизическиеЛица.КонтактнаяИнформация КАК КонтактнаяИнформация
ГДЕ
КонтактнаяИнформация.Вид = &ВидТелефон;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
КонтактнаяИнформация.Ссылка КАК физЛицо,
ЕСТЬNULL(КонтактнаяИнформация.Представление, "") КАК Адрес
ПОМЕСТИТЬ времТабАдрес
ИЗ
Справочник.ФизическиеЛица.КонтактнаяИнформация КАК КонтактнаяИнформация
ГДЕ
КонтактнаяИнформация.Вид = &ВидАдрес;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ФизЛица.Ссылка КАК ФизЛицо,
времТабТелефон.Телефон КАК Телефон,
времТабАдрес.Адрес КАК Адрес
ИЗ
Справочник.ФизическиеЛица КАК ФизЛица
ЛЕВОЕ СОЕДИНЕНИЕ времТабТелефон КАК времТабТелефон
ПО ФизЛица.Ссылка = времТабТелефон.физЛицо
ЛЕВОЕ СОЕДИНЕНИЕ времТабАдрес КАК времТабАдрес
ПО ФизЛица.Ссылка = времТабАдрес.физЛицо
Этот метод более структурирован, однако при большом количестве полей (например, 11 полей, как упоминалось в обсуждении) создание 11 временных таблиц также может замедлить работу СУБД.
Выясним, как получить все данные за один проход по таблице. Это наиболее эффективный способ с точки зрения производительности запроса. Мы используем конструкцию МАКСИМУМ вместе с оператором ВЫБОР.
Проанализируем пример:
ВЫБРАТЬ
КИ.Ссылка КАК ФизЛицо,
МАКСИМУМ(ВЫБОР
КОГДА КИ.Вид = &ВидТелефон
ТОГДА КИ.Представление
ИНАЧЕ ""
КОНЕЦ) КАК Телефон,
МАКСИМУМ(ВЫБОР
КОГДА КИ.Вид = &ВидАдрес
ТОГДА КИ.Представление
ИНАЧЕ ""
КОНЕЦ) КАК Адрес
ИЗ
Справочник.ФизическиеЛица.КонтактнаяИнформация КАК КИ
СГРУППИРОВАТЬ ПО
КИ.Ссылка
Преимущество: СУБД сканирует таблицу КонтактнаяИнформация всего один раз, распределяя значения по колонкам в процессе группировки. Это значительно быстрее, чем 10 соединений одной и той же таблицы самой с собой.
Дополнительные реквизиты в УТ 11 и Рознице 2.2 хранятся в табличной части ДополнительныеРеквизиты. Получение их в колонки происходит по тому же принципу, что и контактной информации. Рассмотрим пример получения доп. реквизита "Дата регистрации анкеты":
ВЫБРАТЬ
ДопРеквизиты.Ссылка КАК ФизЛицо,
МАКСИМУМ(ВЫБОР
КОГДА ДопРеквизиты.Свойство = &СвойствоДатаРегистрации
ТОГДА ДопРеквизиты.Значение
ИНАЧЕ NULL
КОНЕЦ) КАК ДатаРегистрации
ИЗ
Справочник.ФизическиеЛица.ДополнительныеРеквизиты КАК ДопРеквизиты
ГДЕ
ДопРеквизиты.Свойство = &СвойствоДатаРегистрации
СГРУППИРОВАТЬ ПО
ДопРеквизиты.Ссылка
Помните, что поле Значение имеет составной тип. Если вам нужно получить строковое представление (например, для значения из выпадающего списка), используйте функцию ПРЕДСТАВЛЕНИЕ(ДопРеквизиты.Значение).
Если вам не обязательно выполнять все действия именно в одном запросе (например, вы формируете таблицу значений в коде), лучше воспользоваться готовыми инструментами БСП. В конфигурациях есть модуль УправлениеКонтактнойИнформацией, который содержит оптимизированные функции.
Например, функция КонтактнаяИнформацияОбъектов позволяет получить таблицу со всеми данными для массива ссылок:
СписокСсылок = Новый Массив;
СписокСсылок.Добавить(ТекущееФизЛицо);
ТаблицаКИ = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъектов(СписокСсылок);
Также полезно знать о функции СформироватьЗапросКонтактнойИнформацииОбъектов, которая возвращает готовый текст запроса, учитывающий текущие настройки метаданных (хранятся ли данные в ТЧ или в регистре сведений).
Важно помнить, что в зависимости от версии платформы и настроек конфигурации, контактная информация может быть вынесена в отдельный Регистр сведений КонтактнаяИнформация. Если вы видите, что табличная часть справочника пуста, обязательно проверьте этот регистр. Логика построения запроса к регистру будет идентична методу группировки, описанному выше.
Для адресов в поле ЗначенияПолей часто хранится XML или JSON со структурой адреса (город, улица, дом). Если вам нужно вытащить индекс или код КЛАДР, простого обращения к Представление не хватит. В таких случаях мы рекомендуем использовать программный разбор строки функцией УправлениеКонтактнойИнформацией.КонтактнаяИнформацияИзXML().
Таким образом, для решения задачи в 1С:Розница 2.2 и УТ 11 наиболее правильным будет использование метода свертки в запросе или стандартных функций БСП, что обеспечит высокую скорость работы системы даже при больших объемах данных.