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