При разработке отчетов часто возникает задача получить таблицу пар документов, связанных между собой (например, Заявка покупателя и созданная на ее основании Реализация товаров и услуг). Обычное использование стандартного механизма «Структура подчиненности» или объекта метаданных КритерийОтбора хорошо работает для одного конкретного документа, но не подходит для формирования выборки за период. Разберем, как решить эту задачу эффективно и правильно с точки зрения производительности системы.
Проанализируем работу объекта КритерийОтбора.СвязанныеДокументы. В языке запросов 1С этот объект представлен как виртуальная таблица, которая принимает на вход обязательный параметр — ссылку на конкретный документ. Выглядит это так:
ВЫБРАТЬ
СвязанныеДокументы.Ссылка
ИЗ
КритерийОтбора.СвязанныеДокументы(&Док) КАК СвязанныеДокументы
Попытка использовать этот механизм в цикле для каждого документа за период является грубой ошибкой (так называемый «запрос в цикле»), которая катастрофически снижает производительность. Платформа не позволяет соединить обычную таблицу документов с этой виртуальной таблицей так, чтобы параметр передавался динамически для каждой строки. Поэтому нам необходимо найти способ прямого обращения к данным.
Выясним, как именно связаны документы в вашей конфигурации. Если стандартное поле ДокументОснование отсутствует в шапке документа, это означает, что связь реализована через конкретный реквизит. Разберем алгоритм поиска:
В рассматриваемом случае выяснилось, что реквизит связи называется ЗаявкаПокупателя и находится он в табличной части Товары документа РеализацияТоваровУслуг.
Теперь, когда мы знаем имя реквизита, составим запрос. Рассмотрим ситуацию, когда нам нужно получить список всех реализаций и соответствующих им заявок за определенный период. Проанализируем пример кода:
ВЫБРАТЬ РАЗЛИЧНЫЕ
РеализацияТовары.ЗаявкаПокупателя КАК Заявка,
РеализацияТовары.Ссылка КАК Реализация
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
ГДЕ
РеализацияТовары.Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода
И РеализацияТовары.ЗаявкаПокупателя <> ЗНАЧЕНИЕ(Документ.ЗаявкаПокупателя.ПустаяСсылка)
И РеализацияТовары.Ссылка.Проведен = ИСТИНА
Разберем важные моменты в этом запросе:
РеализацияТовары.Ссылка.Дата — это допустимо, но если объем данных огромен, лучше сначала отобрать ссылки на документы реализации в отдельную временную таблицу, а затем соединять их с табличной частью.Если документов за период очень много, запрос к табличным частям может работать медленно. В типовых конфигурациях 1С связь между заказами и отгрузками фиксируется в регистрах накопления (например, ЗаказыПокупателей). Посмотрим, как составить запрос к регистру:
ВЫБРАТЬ РАЗЛИЧНЫЕ
ЗаказыОбороты.ЗаказПокупателя КАК Заявка,
ЗаказыОбороты.Регистратор КАК Реализация
ИЗ
РегистрНакопления.ЗаказыПокупателей.Обороты(&НачалоПериода, &КонецПериода, Регистратор, ) КАК ЗаказыОбороты
ГДЕ
ТИПЗНАЧЕНИЯ(ЗаказыОбороты.Регистратор) = ТИП(Документ.РеализацияТоваровУслуг)
Этот способ является наиболее «профессиональным», так как регистры специально оптимизированы для подобных выборок. Мы используем виртуальную таблицу Обороты с периодичностью Регистратор, что позволяет нам напрямую увидеть, какой документ (Реализация) сделал движение по какому Заказу (Заявке).
Подводя итог, отметим: критерии отбора — это инструмент интерфейса для быстрой навигации пользователя, а не инструмент для построения отчетов. Для получения связанных данных за период следует использовать либо прямые запросы к таблицам документов (если связь в реквизитах), либо запросы к регистрам накопления.
При работе с реквизитами в табличных частях всегда помните про индексацию. В конфигураторе проверьте свойство «Индексировать» у реквизита ЗаявкаПокупателя. Если индекс отсутствует, запрос будет выполнять полное сканирование таблицы (Full Scan), что приведет к блокировкам базы данных при одновременной работе многих пользователей.