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