В практике разработчика 1С часто возникает задача вывести в одном отчете или обработке данные по остаткам на разные моменты времени (в этом поможет Быстрый анализ данных). Например, нам нужно сопоставить «Остатки на начало года» и «Остатки на текущую дату», либо проанализировать срез данных до определенного периода и после него. На первый взгляд задача кажется простой, но при реализации в языке запросов возникают вопросы: какую виртуальную таблицу выбрать, как не потерять данные за последнюю секунду и как обеспечить высокую скорость работы системы. Разберем по шагам все доступные способы решения этой задачи, проанализируем их плюсы и минусы (для тестирования кода пригодится Консоль запросов для управляемых форм).
Самый очевидный и быстрый в написании кода способ — использование виртуальной таблицы ОстаткиИОбороты. Эта таблица специально спроектирована для того, чтобы в рамках одного обращения к базе данных получить и начальное состояние, и конечное, и все движения за период. Рассмотрим, как это выглядит в коде запроса:
ВЫБРАТЬ
ХозрасчетныйОстаткиИОбороты.Счет КАК Счет,
ХозрасчетныйОстаткиИОбороты.СуммаНачальныйОстаток КАК ОстатокНаНачало,
ХозрасчетныйОстаткиИОбороты.СуммаКонечныйОстаток КАК ОстатокНаКонец
ИЗ
РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, , , , , ) КАК ХозрасчетныйОстаткиИОбороты
Проанализируем ситуацию: почему этот способ часто называют «азбукой 1С»? Дело в том, что система сама вычисляет значения на обе даты. Вам не нужно заботиться о соединениях или объединениях. Однако у этого метода есть существенный недостаток — производительность. Таблица ОстаткиИОбороты является самой «тяжелой» для СУБД. Чтобы рассчитать СуммаКонечныйОстаток, система сначала берет итоги на начало месяца, «докручивает» их до &НачалоПериода, а затем прибавляет все обороты за указанный интервал. Если ваш период — год или более, нагрузка на сервер будет значительной. Тем не менее, это позволяет формировать такие отчеты, как Ведомость товаров на складах с датой и количеством минимального остатка.
Если нам критична скорость работы (особенно на больших объемах данных), рекомендуется использовать обращение к виртуальной таблице Остатки. Чтобы получить данные на две даты, мы создаем два отдельных запроса и объединяем их через оператор ОБЪЕДИНИТЬ ВСЕ. Посмотрим на примере регистра бухгалтерии, как правильно разнести данные по разным колонкам:
ВЫБРАТЬ
ОстаткиНаНачало.Счет КАК Счет,
ОстаткиНаНачало.СуммаОстаток КАК СуммаДо,
0 КАК СуммаПосле
ИЗ
РегистрБухгалтерии.Хозрасчетный.Остатки(&Дата1, Счет В (&СписокСчетов), , ) КАК ОстаткиНаНачало
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ОстаткиНаКонец.Счет,
0,
ОстаткиНаКонец.СуммаОстаток
ИЗ
РегистрБухгалтерии.Хозрасчетный.Остатки(&Дата2, Счет В (&СписокСчетов), , ) КАК ОстаткиНаКонец
Рассмотрим подробнее, что происходит в этом коде. Мы создаем «пустые» поля (нули) в каждом подзапросе, чтобы при объединении данные не перемешались в одной колонке. После выполнения этого запроса данные обычно группируют по ключевым полям (счет, номенклатура и т.д.), чтобы схлопнуть строки в одну. Этот метод работает быстрее, так как виртуальная таблица Остатки обращается напрямую к заранее рассчитанным таблицам итогов 1С, выполняя минимум вычислений.
Частая ошибка начинающих разработчиков — путаница с тем, включается ли указанная дата в остатки. По умолчанию в 1С остатки всегда берутся на начало секунды. Если вы укажете дату '2024-01-01 00:00:00', документы, проведенные ровно в это время, не попадут в расчет. Чтобы включить движения последней секунды, нужно использовать объект Граница.
В коде 1С это реализуется следующим образом:
ГраницаКонца = Новый Граница(КонецДня(НужнаяДата), ВидГраницы.Включая);
Запрос.УстановитьПараметр("КонецПериода", ГраницаКонца);
Выясним причину, почему это важно. В таблице ОстаткиИОбороты конечный остаток рассчитывается с учетом движений. Если не использовать Границу, вы можете получить разные цифры при использовании разных виртуальных таблиц на одну и ту же дату. Всегда используйте ВидГраницы.Включая, если вам нужно получить остаток «после» выполнения всех операций в указанный момент времени.
Для того чтобы принять верное решение, проанализируем следующие факторы:
Остатки. Это значительно снизит нагрузку на SQL-сервер.ОстаткиИОбороты — лучший выбор, так как система сделает один проход по данным вместо трех.Остатки и ОстаткиИОбороты могут различаться, если в базе данных давно не выполнялся пересчет итогов. Таблица Остатки берет данные из итогов, а ОстаткиИОбороты может пересчитывать их «на лету» по физическим записям.При работе со счетами (например, 60.01, 08.04), упомянутыми в обсуждении, важно помнить: использование аналитики (субконто) в ОстаткиИОбороты накладывает дополнительные требования к индексам. Если вы фильтруете данные по счету, обязательно передавайте этот фильтр в параметры виртуальной таблицы, а не в условие ГДЕ. Это позволит платформе 1С отсечь лишние записи на уровне обращения к СУБД, не перебирая весь регистр в памяти сервера.
Подводя итог, можно сказать: для простых отчетов с небольшим периодом смело используйте ОстаткиИОбороты. Если же вы проектируете высоконагруженную систему или сложный аналитический отчет за несколько лет — делайте выбор в пользу объединения запросов к таблице Остатки с использованием объекта Граница.