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

Программист 1С v7.7 Управленческий учет Промышленность, строительство и АПК
← На главную

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

Суть технической проблемы

Рассмотрим типичную ситуацию. Программист создает запрос по регистру остатков. В запросе используются стандартные функции для получения итогов. Проблема проявляется странным образом: если период запроса совпадает с границами месяца (например, с 1 по 30 апреля), остатки отображаются верно. Однако, стоит сдвинуть дату начала всего на один день (например, со 2 апреля), как конечный остаток по определенным позициям превращается в ноль. Если же сдвинуть дату конца — пропадает начальный остаток. Проанализируем типичный текст такого «проблемного» запроса:


|Период с ДатаНачала по ДатаКонца;
|Продукт = Регистр.Сыр.Продукт;
|ДатаВарки = Регистр.Сыр.Документ.ДатаДок; // Обращение через точку!
|ЗПодразделение = Регистр.Сыр.Подразделение;
|Группировка ЗПодразделение;
|Группировка Продукт;
|Группировка ДатаВарки; // Группировка по виртуальному полю
|Функция СНД_Г = НачОст(Головы);
|Функция СКД_Г = КонОст(Головы);

Важный момент: в данном примере ДатаВарки получается не напрямую из измерения регистра, а через обращение к реквизиту документа, который является измерением. Именно в этой «точке» кроется причина всех бед.

Разберем внутренние механизмы 1С 7.7

Чтобы понять, почему данные исчезают, нам необходимо заглянуть «под капот» системы. Выясним причины, опираясь на архитектуру хранения данных в SQL-версии 1С 7.7:

  1. Хранение итогов (Таблицы RG): В 1С 7.7 остатки хранятся в специальных таблицах итогов (RG) строго на начало каждого месяца. Если ваш запрос охватывает полный месяц, система просто считывает готовые значения.
  2. Расчет на произвольную дату: Если период запроса начинается не с первого числа месяца, 1С вынуждена вычислять остаток динамически. Формула проста: Остаток на 02.04 = Итоги на 01.04 + Движения за 01.04. Для этого система обращается к таблице движений (RA).
  3. Проблема LEFT JOIN: Когда мы пишем Регистр.Сыр.Документ.ДатаДок, встроенный генератор запросов 1С добавляет соединение (JOIN) с таблицей заголовков документов. При расчете виртуальных остатков (когда данные «докручиваются» движениями), механизм сопоставления итогов из таблицы RG и движений из таблицы RA часто дает сбой, если группировка идет по реквизиту через точку.
  4. Пустые значения: Если реквизит Документ в регистре не заполнен или документ помечен на удаление (и его дата в БД стала неопределенной), соединение через точку возвращает NULL. В этом случае агрегатные функции НачОст и КонОст во встроенных запросах 1С 7.7 часто некорректно отрабатывают группировку, обнуляя результат для всей строки.

Решение №1: Группировка по объектам (Измерениям)

Проанализируем самый эффективный способ исправления ситуации. Основное правило «черного запроса» 1С 7.7 гласит: никогда не используйте обращение через точку в секции группировок, если вам нужны корректные остатки.

Вместо того чтобы группировать по дате документа, мы должны сгруппировать данные по самому документу (измерению). Рассмотрим исправленный код запроса:


// Вместо обращения к реквизиту через точку:
// |ДатаВарки = Регистр.Сыр.Документ.ДатаДок; 
// Используем само измерение напрямую:
|ДокВарки = Регистр.Сыр.Документ; 

|Группировка ЗПодразделение;
|Группировка Продукт;
|Группировка ДокВарки; // Группируем по объекту-ссылке

При таком подходе 1С строит запрос к таблицам итогов и движений напрямую по физическим полям (идентификаторам объектов), что гарантирует математическую точность расчета остатков. Выясним, как же теперь получить дату? Мы сделаем это позже, при обходе результата.

Решение №2: Получение атрибутов при обходе результата

После того как мы изменили группировку на объектную, нам все равно нужно вывести дату в отчет. Рассмотрим, как правильно организовать цикл обработки данных:


Пока Запрос.Группировка(1) = 1 Цикл // Подразделение
    Пока Запрос.Группировка(2) = 1 Цикл // Продукт
        Пока Запрос.Группировка(3) = 1 Цикл // ДокВарки
            // Получаем дату варки напрямую из объекта группировки
            ТекДатаВарки = Запрос.ДокВарки.ДатаДок;
            
            ПечатьСтр(ТекДатаВарки, Запрос.СНД_Г, Запрос.СКД_Г);
        КонецЦикла;
    КонецЦикла;
КонецЦикла;

Хотя этот метод может работать чуть медленнее на огромных выборках (из-за обращения к базе за реквизитом каждого объекта в цикле), он является единственным надежным способом сохранения итогов при использовании штатного механизма запросов.

Решение №3: Использование Группировки "День"

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


|Период с ДатаНачала по ДатаКонца;
|Продукт = Регистр.Сыр.Продукт;
|Группировка Продукт;
|Группировка День; // Автоматическая группировка по датам движений
|Функция Нач = НачОст(Вес);
|Функция Кон = КонОст(Вес);

Важно: этот метод подходит для хронологических отчетов, но будьте осторожны — он может «раздуть» количество строк в выборке, если вы неправильно настроите параметры вывода пустых значений.

Профессиональный подход: Прямые запросы (SQL)

Для тех, кто работает на SQL-версиях 1С 7.7 (как в случае автора вопроса с SQL 2008 R2), существует еще более радикальное и эффективное решение — использование внешних компонент, таких как 1С++.

Прямые запросы позволяют написать текст на чистом T-SQL, обращаясь напрямую к таблицам RG* и RA*. Это полностью снимает проблему «глюков» встроенного языка запросов, позволяет использовать любые типы соединений и работает в десятки (а иногда и в сотни) раз быстрее штатных средств. Если ваш отчет по остаткам сыра становится слишком сложным, рассмотрите возможность перехода на прямой запрос к базе данных.

Подведем итоги и сформируем правила

Проанализировав ситуацию, мы можем составить краткий чек-лист для предотвращения потери остатков в 1С 7.7:

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

← На главную