Почему нельзя установить отбор по регистратору в параметрах виртуальной таблицы и как это правильно сделать?

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

При разработке запросов в системе 1С:Предприятие программисты часто сталкиваются с ошибкой "Неверные параметры" при попытке наложить фильтр на поле Регистратор непосредственно внутри параметров виртуальной таблицы (например, Продажи.Обороты). На первый взгляд это кажется нелогичным: если мы можем выбрать это поле в секции ВЫБРАТЬ, почему мы не можем передать его как параметр для оптимизации выборки?

В этой статье мы подробно разберем внутреннее устройство регистров накопления, выясним причины такого поведения платформы и рассмотрим наиболее эффективные способы решения этой задачи.

Разберем причину возникновения ошибки

Для начала проанализируем, как устроены виртуальные таблицы 1С. Когда мы обращаемся к таблице РегистрНакопления.Продажи.Обороты, платформа не просто читает данные из одной таблицы в базе данных SQL. Она пытается максимально оптимизировать запрос, обращаясь к специальным служебным таблицам — таблицам итогов.

Рассмотрим структуру хранения данных в типичном регистре накопления:

  1. Основная таблица движений: Содержит все записи, сделанные документами. Здесь есть поле Период, Регистратор, НомерСтроки, а также все измерения и ресурсы.
  2. Таблицы итогов (Остатков или Оборотов): Это агрегированные данные. В них информация хранится в разрезе измерений и периодов (обычно кратность — месяц).

Критически важный момент: в таблицах итогов поле Регистратор отсутствует. Итоги хранятся «свернуто». Параметр "Условие" (четвертый параметр виртуальной таблицы Обороты) предназначен для того, чтобы платформа могла наложить фильтр на этапе обращения к таблице итогов. Поскольку регистратора в итогах нет, попытка передать его в параметры вызывает синтаксическую ошибку на уровне парсера запросов 1С.

Проанализируем работу параметра "Периодичность"

Часто возникает вопрос: "Но ведь я могу указать периодичность Регистратор, и тогда поле появится в выборке!". Это верно. Рассмотрим пример такого запроса:


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

В данном случае, указывая периодичность Регистратор, мы заставляем платформу отказаться от использования быстрых таблиц итогов и перейти к сканированию основной таблицы движений. Однако даже в этом случае платформа сохраняет жесткую структуру параметров виртуальной таблицы: в поле "Условие" допускаются только измерения регистра. Это сделано для унификации программного интерфейса запросов.

Решение №1: Использование конструкции ГДЕ

Если вам необходимо получить данные именно из виртуальной таблицы (например, вам нужны обороты за период, но ограниченные конкретным документом), стандартным и правильным способом будет использование секции ГДЕ.

Рассмотрим, как это выглядит в коде:


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

Многие опасаются, что ГДЕ работает медленнее, чем фильтр в параметрах. В большинстве случаев это правда для измерений, так как 1С сначала выбирает все данные, а потом фильтрует их. Но для поля Регистратор ситуация иная. Основная таблица движений регистра всегда индексирована по регистратору. СУБД (SQL Server, PostgreSQL) эффективно использует этот индекс, и скорость выполнения запроса будет практически идентичной той, если бы параметр существовал внутри виртуальной таблицы.

Решение №2: Обращение к основной таблице регистра

Если ваша задача — получить движения одного конкретного документа, то использование виртуальной таблицы Обороты является избыточным (architectural overhead). Виртуальная таблица — это мощный инструмент для расчета итогов за большие периоды. Для данных одного регистратора гораздо эффективнее обращаться напрямую к основной таблице.

Посмотрим на пример правильного обращения к физической таблице:


|ВЫБРАТЬ
|    Продажи.Организация КАК Организация,
|    Продажи.Контрагент КАК Контрагент,
|    Продажи.Номенклатура КАК Номенклатура,
|    Продажи.Сумма КАК СуммаОборот
|ИЗ
|    РегистрНакопления.Продажи КАК Продажи
|ГДЕ
|    Продажи.Регистратор = &Регистратор

Преимущества этого метода:

Сравнение методов: когда какой выбрать?

Выясним, в каких ситуациях стоит использовать тот или иной подход. Выбор зависит от того, что именно вы хотите получить в результате.

Ситуация А: Нужно получить данные только по одному регистратору.
Используйте прямой запрос к таблице регистра. Это самый быстрый путь. Виртуальная таблица здесь не нужна, так как нет задачи суммировать данные разных документов.

Ситуация Б: Нужно получить обороты за период, но отфильтрованные по сложному условию, связанному с регистратором (например, по автору документа).
Используйте виртуальную таблицу с периодичностью Регистратор и условием в ГДЕ.


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

Ситуация В: Нужно получить итоги по измерениям, но исключить движения определенных регистраторов.
Здесь также используется виртуальная таблица с периодичностью Регистратор, так как нам все еще нужна агрегация по измерениям (например, общая сумма продаж по товару), но с детализацией до документа для выполнения фильтрации.

Особенности периодичности "Авто"

Стоит также упомянуть периодичность Авто. Если вы используете её в виртуальной таблице, платформа сама определяет необходимый уровень детализации. Если в списке выбранных полей (ВЫБРАТЬ) есть Регистратор или Период, 1С автоматически поднимет уровень детализации до регистратора. Однако правило параметров остается неизменным: отбор по регистратору в скобках все равно будет вызывать ошибку.

Подведем итоги

Подводя итог нашему анализу, закрепим основные правила работы с регистратором в запросах:

  1. Параметры виртуальной таблицы (в скобках) принимают только измерения. Регистратор — это стандартный реквизит, и его там быть не может.
  2. Для отбора по регистратору в виртуальной таблице используйте ГДЕ. Это не снизит производительность критично, так как поле индексировано.
  3. Если вам не нужны обороты за период, а нужны только данные документа — откажитесь от виртуальной таблицы в пользу физической таблицы движений (РегистрНакопления.ИмяРегистра).
  4. Помните об архитектуре: таблицы итогов хранят данные "безлико", без привязки к конкретным записям, что и является причиной данного ограничения платформы.

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

← На главную