Почему виртуальные таблицы Остатки и ОстаткиИОбороты показывают разные данные в запросах 1С?

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

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

Различие в определении момента времени и границы периода

Рассмотрим самую распространенную причину расхождения — работу с временной осью. Когда мы передаем в параметры виртуальной таблицы дату, система интерпретирует ее по-разному в зависимости от типа таблицы. Выясним причину этого поведения.

Виртуальная таблица Остатки получает данные на момент времени (начало указанной секунды). Если документ был проведен в 23:59:59, и вы запрашиваете остатки на эту же секунду, данные этого документа могут не попасть в расчет, так как запрос смотрит «перед» документом.

В то же время таблица ОстаткиИОбороты при получении конечного остатка по умолчанию включает всю указанную секунду целиком. Посмотрим на пример кода, который часто приводит к ошибке:


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

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

Если в параметре &Период и &КонецПериода передана одна и та же дата типа Дата, результаты могут отличаться. Чтобы решить эту проблему программно, необходимо использовать объект Граница. Это гарантирует, что запрос захватит все движения, включая те, что сделаны в последнюю секунду периода.

Разберем, как правильно установить параметры в коде 1С:


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

Механизмы формирования данных в виртуальных таблицах

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

  1. Таблица «Остатки»: Она обращается к физической таблице итогов, где хранятся рассчитанные значения на начало каждого месяца. К этим итогам система прибавляет обороты из таблицы движений за период от ближайшей точки итогов до целевой даты. Это делает таблицу максимально быстрой для получения текущего состояния ресурсов.
  2. Таблица «ОстаткиИОбороты»: Эта таблица работает сложнее. Если в запросе указана периодичность (например, День), системе нужно рассчитать не только конечный, но и начальный остаток, а также обороты за каждый интервал. Она выполняет гораздо больше соединений и математических операций.

Важный момент: Таблица Остатки оптимизирована. Если итоговый результат по набору измерений равен 0, она может вообще не возвращать эту строку. Таблица ОстаткиИОбороты, напротив, выведет строку, если в периоде был хотя бы один оборот, даже если конечный остаток в итоге стал нулевым.

Повреждение и рассинхронизация итогов

Рассмотрим ситуацию, описанную в сообщении №7: остатки «пропадают» на несколько месяцев в одной таблице, но остаются в другой. Это явный признак нарушения логической целостности базы данных. Выясним, почему так происходит.

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

Для исправления этой ситуации необходимо выполнить регламентную операцию:

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

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

Правила использования фильтров и параметров

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

Посмотрим на пример правильного обращения:


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

Если же мы напишем условие в ГДЕ, платформа сначала попытается рассчитать остатки по ВСЕМ товарам и складам, а уже потом отфильтрует результат. Это не только замедляет работу, но и в ряде случаев (при использовании сложных соединений с NULL) может приводить к неявным расхождениям в результатах выборки из разных таблиц.

Итоги и рекомендации

Для того чтобы ваши запросы всегда возвращали корректные и одинаковые данные, придерживайтесь следующих правил:

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

← На главную