Как получить запросом несколько последних записей по каждой группировке в 1С

Программист 1С v8.3 (Управляемые формы) Промышленность, строительство и АПК
← На главную

В практике разработки на платформе 1С:Предприятие часто возникает задача: получить не просто самую последнюю запись (что легко решается с помощью виртуальной таблицы СрезПоследних), а именно несколько последних записей (например, последние 3 замера) для каждого объекта (измерения). Сложность заключается в том, что стандартная конструкция ВЫБРАТЬ ПЕРВЫЕ N работает для всего результата запроса целиком, а не для каждой группы отдельно.

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

Метод 1: Коррелированный подзапрос (Универсальный способ)

Этот метод считается классическим для языка запросов 1С, в котором отсутствуют оконные функции типа ROW_NUMBER(). Мы проанализируем ситуацию, где для каждой записи основной таблицы мы будем «подсчитывать» количество записей, которые произошли позже нее.

Разберем логику: если для конкретной записи в этом же регистре по тому же буру найдется менее 3-х записей с более поздней датой, значит, эта запись входит в тройку последних. Посмотрим на пример реализации такого запроса, который поможет составить Консоль кода + ИИ-помощник (GigaChat) с учётом метаданных конфигурации:


ВЫБРАТЬ
    РС.Период КАК Период,
    РС.Бур КАК Бур,
    РС.Прохождение КАК Прохождение
ИЗ
    РегистрСведений.ПрохождениеБуров КАК РС
ГДЕ
    (ВЫБРАТЬ
        КОЛИЧЕСТВО(РАЗЛИЧНЫЕ РС_Б.Период)
    ИЗ
        РегистрСведений.ПрохождениеБуров КАК РС_Б
    ГДЕ
        РС_Б.Бур = РС.Бур
        И РС_Б.Период > РС.Период) < 3
УПОРЯДОЧИТЬ ПО
    Бур,
    Период УБЫВ

Важные нюансы метода:

  1. В условии КОЛИЧЕСТВО(РАЗЛИЧНЫЕ РС_Б.Период) < 3 цифра 3 означает количество последних записей. Если нужно 5 записей — меняем на 5.
  2. Этот метод может быть медленным на очень больших таблицах, так как подзапрос выполняется для каждой строки. Чтобы оптимизировать выполнение, рекомендуется предварительно отобрать данные во временную таблицу.

Метод 2: Использование Системы компоновки данных (СКД)

Если ваша задача — вывести данные в отчет, то писать сложный запрос вовсе не обязательно (как показывает Простой пример отчета СКД с выводом другого внешнего отчета в один табличный документ на УФ). Платформа 1С предоставляет встроенный механизм ограничения количества записей в группировках. Рассмотрим, как это настроить:

  1. В схеме компоновки данных создаем обычный запрос, выбирающий все записи регистра.
  2. Переходим на закладку «Настройки».
  3. Выбираем группировку по полю Бур.
  4. Внутри этой группировки создаем детальные записи (или вложенную группировку).
  5. Выделяем детальные записи и переходим в «Дополнительные настройки» (внизу).
  6. Находим параметр «Тип ограничения количества записей» и устанавливаем значение Топ.
  7. В параметре «Количество записей» указываем нужное число (например, 3).
  8. Критически важно: на уровне этой группировки установите сортировку по полю Период (направление — Убывание).

Проанализируем результат: СКД автоматически применит алгоритм выборки первых N строк для каждого значения измерения Бур.

Метод 3: Работа с уникальностью при периодичности «День»

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

Чтобы решить эту проблему, мы должны использовать Момент Времени или комбинацию полей Регистратор и НомерСтроки (изучить свойства которых поможет Информер по метаданным). Рассмотрим пример правильного условия связи для обеспечения уникальности:


ГДЕ
    РС1.Период < РС2.Период 
    ИЛИ (РС1.Период = РС2.Период И РС1.Регистратор.МоментВремени < РС2.Регистратор.МоментВремени)

Такой подход «разрезает» записи с одинаковой датой, выстраивая их в строгую очередь на основе времени регистрации документа в системе.

Метод 4: Метод «Лестницы» (для фиксированного количества строк)

Если нам нужно гарантированно и быстро получить ровно 2 или 3 записи, и мы хотим избежать вложенных запросов в условии ГДЕ, можно использовать последовательное объединение временных таблиц. Разберем по шагам:

  1. Шаг 1: Получаем максимальные даты для каждого бура (аналог СрезПоследних) и помещаем во временную таблицу ВТ_Макс1.
  2. Шаг 2: Делаем второй запрос, где выбираем максимальные даты, исключая те, что уже попали в ВТ_Макс1. Результат кладем в ВТ_Макс2.
  3. Шаг 3: Повторяем процедуру для получения третьей даты в ВТ_Макс3.
  4. Шаг 4: Объединяем (ОБЪЕДИНИТЬ ВСЕ) данные из трех таблиц и соединяем их с основной таблицей регистра для получения ресурсов (например, прохождения бура).

Посмотрим, как выглядит выборка второй «максимальной» даты:


ВЫБРАТЬ
    РС.Бур,
    МАКСИМУМ(РС.Период) КАК Период
ИЗ
    РегистрСведений.ПрохождениеБуров КАК РС
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Макс1 КАК ВТ_Макс1
    ПО РС.Бур = ВТ_Макс1.Бур
    И РС.Период = ВТ_Макс1.Период
ГДЕ
    ВТ_Макс1.Бур ЕСТЬ NULL
СГРУППИРОВАТЬ ПО
    РС.Бур

Выводы и рекомендации по производительности

Проанализировав все способы, мы можем дать следующие советы:

  1. Если вы строите отчет — используйте настройки СКД. Это самый быстрый в разработке и достаточно производительный метод.
  2. Если данные нужны в коде (в обработке) — используйте коррелированный подзапрос, но предварительно ограничьте выборку данных (например, за последний месяц), чтобы не сканировать весь регистр за несколько лет.
  3. Всегда учитывайте возможность существования записей с одинаковым периодом. Используйте Регистратор для уточнения порядка, иначе результат запроса может меняться случайным образом при каждом запуске.

Используя эти методы, мы сможем эффективно решать задачи по анализу истории изменений в регистрах 1С, получая актуальные срезы данных в нужных разрезах.

← На главную