При переходе от простых запросов к физической таблице регистра накопления к получению итогов через виртуальную таблицу Остатки разработчики нередко сталкиваются с ошибкой вида «Поле не найдено». Разберем типичные причины такого поведения платформы 1С:Предприятие, выясним внутреннюю логику виртуальных таблиц и научимся правильно составлять запросы для получения актуальных остатков.
Рассмотрим распространенный ошибочный запрос, в котором выбираются поля с теми же именами, что и в структуре регистра:
ВЫБРАТЬ
РегистрДепозитВодителя.ДепозитИтого,
РегистрДепозитВодителя.Водитель
ИЗ
РегистрНакопления.РегистрДепозитВодителя.Остатки(&ВыбДата, Водитель = &ВыбВодитель) КАК РегистрДепозитВодителя
При выполнении такого кода платформа выдаст ошибку:
{(2, 27)}: Поле не найдено "РегистрДепозитВодителя.ДепозитИтого"
Проанализируем ситуацию и выделим три ключевые причины, приводящие к подобным сбоям:
Остатки имена ресурсов не совпадают с их именами в метаданных. К каждому ресурсу платформа автоматически добавляет постфикс Остаток. Например, поле ДепозитИтого превращается в ДепозитИтогоОстаток.Водитель ошибочно создан как реквизит) вызовет ошибку отсутствия поля.ИЗ ... КАК Псевдоним, забывая скорректировать префиксы полей в секции ВЫБРАТЬ.Чтобы виртуальная таблица остатков работала корректно, проверим структуру регистра в дереве конфигурации:
Водитель должно находиться строго в ветке «Измерения». Только в этом случае по нему будут рассчитываться итоги и к нему можно будет обратиться в запросе остатков.ДепозитИтого, ДолженВКассуЕЩЕ, СданоВКассу должны располагаться в ветке «Ресурсы».Остаток: ДепозитИтогоОстаток, ДолженВКассуЕЩЕОстаток, СданоВКассуОстаток. К измерению Водитель суффикс не добавляется.Разберем по шагам, как составить рабочий код запроса с передачей периода и параметров отбора:
&НаСервере
Процедура ПолучитьОстаткиПоВодителю()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РегистрОстатки.Водитель КАК Водитель,
| РегистрОстатки.ДепозитИтогоОстаток КАК ДепозитИтого,
| РегистрОстатки.ДолженВКассуЕЩЕОстаток КАК ДолженВКассуЕЩЕ,
| РегистрОстатки.СданоВКассуОстаток КАК СданоВКассу
|ИЗ
| РегистрНакопления.РегистрДепозитВодителя.Остатки(
| &ВыбДата,
| Водитель = &ВыбВодитель
| ) КАК РегистрОстатки
|УПОРЯДОЧИТЬ ПО
| Водитель УБЫВ";
// Указываем границу периода для включения движений на крайнюю секунду
Запрос.УстановитьПараметр(
"ВыбДата",
Новый Граница('20170609235959', ВидГраницы.Включая)
);
// Передаем ссылку на конкретного водителя
Запрос.УстановитьПараметр(
"ВыбВодитель",
Справочники.Водители.НайтиПоНаименованию("Силкин")
);
Результат = Запрос.Выполнить().Выбрать();
Пока Результат.Следующий() Цикл
Сообщить(
"Водитель: " + СокрЛП(Результат.Водитель) +
" | Депозит: " + Результат.ДепозитИтого +
" | Должен: " + Результат.ДолженВКассуЕЩЕ +
" | Сдано: " + Результат.СданоВКассу
);
КонецЦикла;
КонецПроцедуры
Обратим внимание на наложение условий. Условие по измерению всегда следует указывать во втором параметре виртуальной таблицы: Остатки(&Период, Водитель = &ВыбВодитель).
Если написать фильтр в общей секции ГДЕ:
ИЗ
РегистрНакопления.РегистрДепозитВодителя.Остатки(&ВыбДата) КАК РегистрОстатки
ГДЕ
РегистрОстатки.Водитель = &ВыбВодитель
СУБД сначала рассчитает остатки по всем существующим водителям в базе данных, сформирует огромную временную таблицу и только потом отфильтрует строки. Наложение отбора в параметрах виртуальной таблицы заставляет платформу считывать остатки только по указанному значению, что кардинально повышает скорость выполнения запроса.
Выясним разницу между передачей различных типов в параметр периода виртуальной таблицы:
Остатки() без первого параметра, платформа считает готовые актуальные остатки из таблицы итогов без дополнительных расчетов по таблице движений.23:59:59, движения, записанные в эту секунду, в остаток не войдут.Новый Граница(Дата, ВидГраницы.Включая) принудительно включает в расчет движения, проведенные в указанную секунду.Ссылка.МоментВремени(), чтобы учесть позицию документа относительно других документов той же секунды.Для предотвращения подобных синтаксических ошибок всегда рекомендуется пользоваться встроенным Конструктором запроса. Конструктор автоматически анализирует метаданные регистра, отображает только доступные для выборки поля с корректными суффиксами (Остаток для ресурсов) и скрывает недоступные реквизиты, исключая возникновение ошибки «Поле не найдено».