Рассмотрим частую проблему, с которой сталкиваются разработчики в 1С:Предприятие 7.7 при написании запросов к регистрам. Зачастую код выполняется без ошибок, транслятор сообщает об успешном выполнении, но результат оказывается пустым, и цикл обхода не инициируется. Разберем по шагам, почему так происходит и как правильно составить запрос, чтобы данные загружались корректно.
Посмотрим на классический пример проблемного кода, который возвращает пустой результат:
ПЕРИОД С '01.10.20' ПО '31.12.20';
ОБРАБАТЫВАТЬДОКУМЕНТЫ ВСЕ;
Фирма = Регистр.ГТД.Фирма;
Товар = Регистр.ГТД.Товар;
ГТД = Регистр.ГТД.ГТД;
ОстатокТовара = Регистр.ГТД.ОстатокТовара;
ТекущийДокумент = Регистр.ГТД.ТекущийДокумент;
ГРУППИРОВКА ТекущийДокумент;
На первый взгляд, все нужные переменные объявлены, группировка задана, но при вызове метода обхода система не находит ни одной записи. Выясним причину такого поведения движка 1С 7.7 и исправим недочеты.
Главная ошибка кроется во внутреннем механизме работы компилятора «черных запросов». В версии 1С 7.7, когда мы обращаемся к регистрам (как остатков, так и оборотов), система определяет физические таблицы для чтения исключительно на основании объявленных функций. Если в тексте запроса нет ни одной агрегатной функции, платформа считает, что вычислять нечего, и вообще не инициирует выборку данных из базы.
Добавим в текст запроса функцию расчета конечного остатка:
Функция КолКонОст = КонОст(ОстатокТовара);
Для регистров остатков также подойдут НачОст, Приход, Расход, а для оборотных регистров — Сумма.
В исходном коде используется явное объявление переменной ТекущийДокумент = Регистр.ГТД.ТекущийДокумент;. Разберем, почему это излишне. В языке запросов 7.7 слово Документ является системным и зарезервированным. При обращении к регистру оно автоматически ссылается на документ-регистратор, который сделал движение. Упростим наш код, удалив объявление переменной и изменив саму группировку:
ГРУППИРОВКА Документ;
Проанализируем строку ОБРАБАТЫВАТЬДОКУМЕНТЫ ВСЕ;. Эта директива имеет смысл только тогда, когда базовым объектом выборки являются сами документы (например, при выборке элементов справочников или журналов документов). При работе с регистрами чтение всегда идет из таблиц движений, в которых физически хранятся только данные проведенных документов. Наличие этой директивы в запросе к регистру может замедлить работу или сбить логику транслятора. Рекомендуем её полностью удалить.
Посмотрим на цикл обхода результата. Изначальный вариант выглядел так:
Сообщить(Запрос.ТекущийДокумент.ТекущийДокумент());
Метод ТекущийДокумент() в 1С 7.7 используется для явного позиционирования на объекте, и его вызов заставляет систему выполнять дополнительный (и довольно ресурсоемкий) SQL- или DBF-запрос к базе данных. Так как наша новая группировка называется Документ, системная переменная Запрос.Документ уже содержит готовую ссылку на документ. Ускорим обход, исключив лишние методы:
Пока Запрос.Группировка("Документ") = 1 Цикл
Сообщить(Запрос.Документ);
КонецЦикла;
Соберем все наши улучшения и оптимизации воедино. Проанализируем итоговый правильный текст запроса к регистру:
ПЕРИОД С '01.10.20' ПО '31.12.20';
Фирма = Регистр.ГТД.Фирма;
Товар = Регистр.ГТД.Товар;
ГТД = Регистр.ГТД.ГТД;
ОстатокТовара = Регистр.ГТД.ОстатокТовара;
// Обязательная функция для инициализации выборки движком
Функция КолКонОст = КонОст(ОстатокТовара);
// Системная группировка по регистратору без лишних переменных
ГРУППИРОВКА Документ;
С таким кодом платформа корректно обратится к физическим таблицам регистра, соберет данные об остатках и сгруппирует их по документам-регистраторам. Применяйте этот подход при разработке и доработке конфигураций в 1С 7.7, чтобы избегать ошибок пустых результатов и неоправданной нагрузки на базу данных.