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

Программист 1С v8.3 (Обычные формы)
← На главную

В практике разработки на платформе 1С:Предприятие 8 часто возникает задача получения актуального состояния данных из периодических регистров сведений. Начинающие программисты нередко сталкиваются с ситуацией, когда запрос возвращает «лишние» строки — например, записи, которые уже были отменены или изменены в более поздние периоды. Рассмотрим, почему это происходит и как составить запрос правильно, используя механизмы платформы.

Разбор типичной ошибки: запрос к физической таблице

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


Запрос.Текст =
    "ВЫБРАТЬ 
    |    КонтрВып.Ном КАК Ном,
    |    КонтрВып.Место КАК Место,
    |    КонтрВып.Зн КАК Зн
    |ИЗ
    |    РегистрСведений.КонтрВып КАК КонтрВып
    |ГДЕ
    |    (КонтрВып.Место = &Место ИЛИ КонтрВып.Место = &Место2) 
    |    И КонтрВып.Зн = ИСТИНА 
    |    И КонтрВып.Период <= &д2";

Выясним причину проблемы: Физическая таблица регистра сведений (РегистрСведений.ИмяРегистра) хранит всю историю изменений. Если по одной и той же номенклатуре (измерение Ном) сначала была сделана запись со значением ИСТИНА, а через неделю — запись со значением ЛОЖЬ, то в физической таблице будут присутствовать обе эти строки. При выполнении запроса с условием Период <= &д2 система честно выберет все записи, дата которых меньше или равна указанной. Если в истории была хотя бы одна запись ИСТИНА, она попадет в результат, даже если позже статус изменился на ЛОЖЬ.

Решение: использование виртуальной таблицы СрезПоследних

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

Рассмотрим, как должен выглядеть правильный запрос:


ВЫБРАТЬ 
    КонтрВып.Ном КАК Ном,
    КонтрВып.Место КАК Место,
    КонтрВып.Зн КАК Зн
ИЗ
    РегистрСведений.КонтрВып.СрезПоследних(&д2, ) КАК КонтрВып
ГДЕ
    КонтрВып.Зн = ИСТИНА

В данном случае платформа сначала найдет актуальные записи на дату &д2, а затем среди них отфильтрует те, у которых ресурс Зн равен ИСТИНА. Если последняя запись по товару имеет значение ЛОЖЬ, она просто не попадет в итоговую выборку.

Оптимизация запроса: параметры виртуальной таблицы

Важно помнить об эффективности кода. Если мы накладываем условия (фильтры) в секции ГДЕ, система сначала строит срез последних по всему регистру, а уже потом фильтрует результат. При большом объеме данных это может привести к значительным задержкам.

Правильный подход — передавать фильтры по измерениям непосредственно в параметры виртуальной таблицы. Разберем по шагам, как это сделать:

  1. Объединим разрозненные условия по местам и группам в массивы или списки значений.
  2. Передадим эти списки в параметры запроса.
  3. Укажем условия внутри скобок СрезПоследних.

Проанализируем оптимизированный пример:


Запрос.Текст = 
    "ВЫБРАТЬ
    |    КонтрВып.Ном КАК Ном,
    |    КонтрВып.Место КАК Место,
    |    КонтрВып.Зн КАК Зн
    |ИЗ
    |    РегистрСведений.КонтрВып.СрезПоследних(&Период, 
    |        Место В (&СписокМест) 
    |        И Ном В ИЕРАРХИИ (&СписокГрупп)
    |    ) КАК КонтрВып
    |ГДЕ
    |    КонтрВып.Зн";

Обратите внимание на несколько важных моментов:

Особенности регистров, подчиненных регистратору

Если ваш регистр имеет режим записи "Подчинение регистратору", это не меняет логику использования СрезПоследних. Однако стоит учитывать, что актуальность записи в таком регистре определяется не только датой, но и позицией документа на оси времени (моментом времени). Виртуальная таблица СрезПоследних корректно обрабатывает такие ситуации, учитывая последовательность документов, проведенных даже в пределах одной секунды.

Почему может не работать СрезПоследних?

Иногда программисты жалуются, что даже СрезПоследних возвращает «не те» данные. Проанализируем возможные причины:

  1. Не указана дата (период): Если в параметр Период виртуальной таблицы не передать значение, 1С вернет срез на текущий момент времени (на самую последнюю запись в базе). Если вам нужны данные на начало дня или на конкретный документ, параметр обязателен.
  2. Пустые измерения: Если в регистре разрешены пустые значения измерений, записи с пустым Ном или Место будут считаться отдельными уникальными комбинациями.
  3. Составной тип данных: Если ресурс Зн имеет составной тип, простое условие ГДЕ Зн может работать некорректно. В этом случае лучше явно проверять Зн = ИСТИНА.

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

← На главную