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