В практике разработки на платформе 1С:Предприятие 8 часто возникает задача получения актуального состояния данных из периодических регистров сведений. Начинающие программисты нередко сталкиваются с ситуацией, когда запрос возвращает «лишние» строки — например, записи, которые уже были отменены или изменены в более поздние периоды. Рассмотрим, почему это происходит и как составить запрос правильно, используя механизмы платформы.
Проанализируем ситуацию, с которой столкнулся автор темы. В его исходном коде запрос шел напрямую к основной (физической) таблице регистра:
Запрос.Текст =
"ВЫБРАТЬ
| КонтрВып.Ном КАК Ном,
| КонтрВып.Место КАК Место,
| КонтрВып.Зн КАК Зн
|ИЗ
| РегистрСведений.КонтрВып КАК КонтрВып
|ГДЕ
| (КонтрВып.Место = &Место ИЛИ КонтрВып.Место = &Место2)
| И КонтрВып.Зн = ИСТИНА
| И КонтрВып.Период <= &д2";
Выясним причину проблемы: Физическая таблица регистра сведений (РегистрСведений.ИмяРегистра) хранит всю историю изменений. Если по одной и той же номенклатуре (измерение Ном) сначала была сделана запись со значением ИСТИНА, а через неделю — запись со значением ЛОЖЬ, то в физической таблице будут присутствовать обе эти строки. При выполнении запроса с условием Период <= &д2 система честно выберет все записи, дата которых меньше или равна указанной. Если в истории была хотя бы одна запись ИСТИНА, она попадет в результат, даже если позже статус изменился на ЛОЖЬ.
Для того чтобы получить только актуальное значение на конкретный момент времени, в 1С предусмотрена виртуальная таблица СрезПоследних. Платформа самостоятельно вычисляет последнюю запись для каждой уникальной комбинации измерений, избавляя разработчика от необходимости писать сложные вложенные запросы с поиском максимальной даты.
Рассмотрим, как должен выглядеть правильный запрос:
ВЫБРАТЬ
КонтрВып.Ном КАК Ном,
КонтрВып.Место КАК Место,
КонтрВып.Зн КАК Зн
ИЗ
РегистрСведений.КонтрВып.СрезПоследних(&д2, ) КАК КонтрВып
ГДЕ
КонтрВып.Зн = ИСТИНА
В данном случае платформа сначала найдет актуальные записи на дату &д2, а затем среди них отфильтрует те, у которых ресурс Зн равен ИСТИНА. Если последняя запись по товару имеет значение ЛОЖЬ, она просто не попадет в итоговую выборку.
Важно помнить об эффективности кода. Если мы накладываем условия (фильтры) в секции ГДЕ, система сначала строит срез последних по всему регистру, а уже потом фильтрует результат. При большом объеме данных это может привести к значительным задержкам.
Правильный подход — передавать фильтры по измерениям непосредственно в параметры виртуальной таблицы. Разберем по шагам, как это сделать:
СрезПоследних.Проанализируем оптимизированный пример:
Запрос.Текст =
"ВЫБРАТЬ
| КонтрВып.Ном КАК Ном,
| КонтрВып.Место КАК Место,
| КонтрВып.Зн КАК Зн
|ИЗ
| РегистрСведений.КонтрВып.СрезПоследних(&Период,
| Место В (&СписокМест)
| И Ном В ИЕРАРХИИ (&СписокГрупп)
| ) КАК КонтрВып
|ГДЕ
| КонтрВып.Зн";
Обратите внимание на несколько важных моментов:
В ИЕРАРХИИ позволяет эффективно искать товары, входящие в определенные группы справочника.ГДЕ достаточно просто написать имя поля (ГДЕ КонтрВып.Зн), так как оно само по себе является логическим выражением. Избыточные конструкции вроде Зн = ИСТИНА И Зн <> ЛОЖЬ только загромождают код.Если ваш регистр имеет режим записи "Подчинение регистратору", это не меняет логику использования СрезПоследних. Однако стоит учитывать, что актуальность записи в таком регистре определяется не только датой, но и позицией документа на оси времени (моментом времени). Виртуальная таблица СрезПоследних корректно обрабатывает такие ситуации, учитывая последовательность документов, проведенных даже в пределах одной секунды.
Иногда программисты жалуются, что даже СрезПоследних возвращает «не те» данные. Проанализируем возможные причины:
Период виртуальной таблицы не передать значение, 1С вернет срез на текущий момент времени (на самую последнюю запись в базе). Если вам нужны данные на начало дня или на конкретный документ, параметр обязателен.Ном или Место будут считаться отдельными уникальными комбинациями.Зн имеет составной тип, простое условие ГДЕ Зн может работать некорректно. В этом случае лучше явно проверять Зн = ИСТИНА.Подведем итог: Для получения текущих статусов, цен, остатков или любых других периодических данных всегда используйте виртуальные таблицы. Это гарантирует получение только актуальной информации и значительно упрощает структуру вашего SQL-запроса, который генерирует платформа 1С.