Как выбрать записи с максимальным значением измерения из регистра накопления в 1С?

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

Зачастую при проектировании архитектуры бюджетирования или сложного учета возникает потребность хранить версии корректировок. Представим ситуацию: у нас имеется регистр накопления с измерениями Организация, Статья и НомерКорректировки (число), а также некий ресурс. Наша задача — получить в отчет данные только по максимально проведенной корректировке для каждой пары Организации и Статьи. Разберем по шагам, как правильно составить такой запрос, и проанализируем архитектурные нюансы.

Решение 1: Использование внутреннего соединения со вложенным запросом

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


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

Важно понимать, почему мы используем ВНУТРЕННЕЕ СОЕДИНЕНИЕ. Левое соединение в данной ситуации не подойдет, так как оно оставит все исходные записи, а наша задача — отсечь те строки, где номер корректировки не является максимальным.

Решение 2: Использование оператора В (IN) с несколькими полями

Платформа 1С позволяет проверять вхождение сразу нескольких полей в результат вложенного запроса. Посмотрим на пример, как можно переписать предыдущий запрос более компактно:


ВЫБРАТЬ
   Бюджет.Организация КАК Организация,
   Бюджет.Статья КАК Статья,
   Бюджет.НомерКорректировки КАК НомерКорректировки,
   Бюджет.Ресурс КАК Ресурс
 ИЗ
   РегистрНакопления.Бюджет КАК Бюджет
 ГДЕ
   (Бюджет.Организация, Бюджет.Статья, Бюджет.НомерКорректировки) В
        (ВЫБРАТЬ
           Бюджет.Организация КАК Организация,
           Бюджет.Статья КАК Статья,
           МАКСИМУМ(Бюджет.НомерКорректировки) КАК НомерКорректировки
         ИЗ
           РегистрНакопления.Бюджет КАК Бюджет
         СГРУППИРОВАТЬ ПО
           Бюджет.Организация,
           Бюджет.Статья)

Такой код выглядит эстетичнее, однако стоит помнить об особенностях оптимизатора СУБД. При больших объемах данных конструкция `В` может быть преобразована в `EXISTS`, что на некоторых серверах (например, PostgreSQL) может привести к выбору неоптимального плана выполнения (Nested Loops).

Решение 3: Оптимизация для больших объемов данных (Временные таблицы)

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

  1. Делаем выборку нужных нам данных (с отборами по периоду или организации) в первую временную таблицу ВТ_ЧерновыеДанные.
  2. Обращаемся к ВТ_ЧерновыеДанные, группируем по измерениям и находим максимум по корректировке. Помещаем результат во вторую таблицу ВТ_Максимумы.
  3. Соединяем ВТ_ЧерновыеДанные и ВТ_Максимумы внутренним соединением.

Разбиение на временные таблицы дает планировщику СУБД четкое представление об объемах данных и позволяет использовать индексы более эффективно.

Архитектурные нюансы: правильно ли использовать регистр накопления?

Выясним причину, почему такие запросы вообще приходится писать. Основная проблема заключается в попытке реализовать механизм версионирования на базе регистра накопления.

Ограничения и рекомендации:

  1. Назначение объектов: Регистры накопления математически спроектированы для быстрого расчета итогов (остатков и оборотов). Если вам нужно хранить актуальное состояние ресурса (последнюю версию или срез показателей бюджетирования), для этого предназначен Регистр сведений.
  2. Срез последних: Платформа генерирует удобные виртуальные таблицы СрезПоследних только для регистров сведений. Размещая номера корректировок в измерении регистра накопления, вы лишаете себя этих готовых и оптимизированных механизмов.
  3. Измерения числового типа: Разработчики платформы крайне не рекомендуют делать измерения примитивных типов (число, строка), если это не обусловлено строгой необходимостью, так как это раздувает индексы и усложняет работу системы.

Как сделать лучше?

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

← На главную