Как правильно ограничить данные по периоду в запросе 1С?

Программист 1С v8.3 (Обычные формы) Управленческий учет Сфера услуг, туризм и социальный сектор
← На главную

При разработке отчетов и обработок в системе 1С программисты часто сталкиваются с задачей получения данных из регистров накопления за определенный интервал времени. Ошибка в выборе виртуальной таблицы или неправильное указание параметров может привести к некорректным результатам или крайне медленной работе программы. В этой статье мы подробно разберем, как правильно ограничить выборку данных по периоду, проанализируем типичные ошибки и рассмотрим эффективные методы решения подобных задач.

Разбор проблемы: Остатки против Остатков и Оборотов

Рассмотрим ситуацию, с которой столкнулся автор темы. Изначально была попытка использовать виртуальную таблицу Остатки. Важно понимать фундаментальное отличие: таблица Остатки предназначена для получения «среза» данных на конкретный момент времени. У нее есть только один параметр периода — дата, на которую нужно рассчитать итоги. Если мы пытаемся наложить условие ГДЕ по дате документа на эту таблицу, мы совершаем методологическую ошибку.

Проанализируем пример кода, который не давал нужного результата:


ВЫБРАТЬ
    РасчетыПоРаботамОстатки.Исполнитель,
    РасчетыПоРаботамОстатки.Работа КАК Услуга,
    ЗаказНарядУслуги.ДатаИВремяВыполнения КАК Выполнено
ИЗ
    РегистрНакопления.РасчетыПоРаботам.Остатки(&Период, ) КАК РасчетыПоРаботамОстатки
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказНаряд.Услуги КАК ЗаказНарядУслуги
    ПО РасчетыПоРаботамОстатки.ЗаказНаряд = ЗаказНарядУслуги.Ссылка
ГДЕ
    ЗаказНарядУслуги.Ссылка.Дата >= &ДатаНачала

В данном случае система сначала получает все остатки на дату &Период, а затем пытается отфильтровать их по дате документа из табличной части. Если за указанный период движений не было, но остаток «висит» с прошлого года, он попадет в выборку, что противоречит задаче получить данные именно «за период».

Использование виртуальной таблицы ОстаткиИОбороты

Если нам необходимо видеть движения (обороты) внутри интервала времени и при этом знать остатки на начало и конец этого интервала, следует использовать таблицу ОстаткиИОбороты. Разберем по шагам, как правильно настроить параметры этой таблицы.

Синтаксис таблицы выглядит следующим образом: ОстаткиИОбороты(&НачалоПериода, &КонецПериода, &Периодичность, &МетодДополнения, &Условие). Посмотрим на исправленный вариант запроса:


ВЫБРАТЬ
    РасчетыПоРаботамОстаткиИОбороты.Исполнитель КАК Исполнитель,
    РасчетыПоРаботамОстаткиИОбороты.Работа КАК Услуга,
    РасчетыПоРаботамОстаткиИОбороты.ЗаказНаряд КАК ЗаказНаряд,
    РасчетыПоРаботамОстаткиИОбороты.СуммаКонечныйОстаток КАК Сумма
ИЗ
    РегистрНакопления.РасчетыПоРаботам.ОстаткиИОбороты(&НачДата, &КонДата, , , ) КАК РасчетыПоРаботамОстаткиИОбороты

В этом примере параметры &НачДата и &КонДата жестко ограничивают данные регистра. Система не будет просматривать лишние записи, что значительно ускоряет выполнение запроса.

Важность фильтрации в параметрах виртуальной таблицы

Одним из ключевых правил профессиональной разработки на 1С является установка условий именно в параметрах виртуальной таблицы, а не в секции ГДЕ. Проанализируем почему:

  1. Производительность: Когда условие передается в параметры (в скобках), СУБД получает уже отфильтрованную выборку. Если условие стоит в ГДЕ, система сначала выбирает все записи (или строит тяжелую таблицу), а потом «выбрасывает» лишнее.
  2. Индексы: Платформа 1С оптимизирует запросы к виртуальным таблицам на уровне SQL, используя встроенные индексы итогов, если параметры переданы корректно.

Метод «Граница» для включения последней секунды

В коде часто встречается конструкция КонецДня(ДатаОкончания) + 1. Это делается для того, чтобы включить документы, записанные в самую последнюю секунду дня. Однако более изящным и правильным способом является использование объекта Граница. Рассмотрим пример кода на встроенном языке:


ГраницаКон = Новый Граница(КонецДня(Объект.ДатаОкончания), ВидГраницы.Включая);
Запрос.УстановитьПараметр("КонДата", ГраницаКон);

Объект Граница гарантирует, что в выборку попадут все движения, включая те, что были сделаны в последнюю секунду указанного периода, не прибегая к искусственному добавлению времени.

Оптимизация соединений и обращений через точку

В обсуждении было замечено использование соединения с табличной частью документа: ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказНаряд.Услуги. Выясним, почему это может быть опасно. Табличные части документов могут быть огромными. Если вам нужно просто получить дату выполнения, как предложили в одном из сообщений, можно использовать обращение через точку:

РасчетыПоРаботамОстатки.ЗаказНаряд.ДатаИВремяВыполнения

Однако помните: каждое обращение через точку от ссылочного поля — это неявное левое соединение в SQL-запросе. Если таких полей много, запрос станет «тяжелым». Если производительность критична, рекомендуется предварительно выбрать данные из регистра во Временную таблицу, проиндексировать ее по полю ЗаказНаряд, и только потом соединять с основной таблицей.

Причина «невидимости» начальной даты

Проанализируем ситуацию, когда запрос в консоли работает правильно, а в коде «не видит» начальную дату. Как выяснилось в ходе обсуждения, проблема часто кроется не в самом запросе, а в логике записи данных. При перепроведении документов в поле периода регистра может записываться дата фактического проведения, а не дата самого документа.

Совет: Всегда проверяйте, какие именно данные лежат в физической таблице регистра (через консоль запросов или просмотр движений документа), прежде чем искать ошибку в параметрах &НачДата и &КонДата. Если итоги регистра не актуальны, может потребоваться процедура «Пересчет итогов» в конфигураторе или через управление итогами в режиме предприятия.

Итоги

Для правильного ограничения данных по периоду в 1С мы рекомендуем:

  1. Использовать ОстаткиИОбороты, если нужен интервал, и Остатки, если нужен срез на момент.
  2. Передавать даты начала и конца строго в параметры виртуальной таблицы.
  3. Использовать объект Граница для точного захвата конца периода.
  4. Минимизировать соединения с тяжелыми табличными частями документов, отдавая предпочтение временным таблицам с индексами.
← На главную