В процессе разработки отчетов или обработки данных в 1С часто возникает задача: для каждой строки документа нужно получить актуальное значение из регистра сведений на момент времени этого документа. Разберем, почему стандартная виртуальная таблица СрезПоследних не подходит для прямой передачи параметра из другой таблицы и какие способы решения существуют.
Виртуальная таблица СрезПоследних является механизмом, который платформа 1С выполняет один раз при инициализации запроса. Она «не видит» значения из текущей строки вашего основного набора данных (например, Событие.Дата), так как параметры виртуальных таблиц должны быть известны до момента исполнения запроса к СУБД. Попытка передать туда поле из другой таблицы приведет к ошибке синтаксиса или неверному результату.
Самый гибкий способ решить эту задачу — отказаться от виртуальной таблицы и работать напрямую с физической таблицей регистра. Суть метода заключается в нахождении максимального периода, который меньше или равен дате нашего документа.
Разберем алгоритм действий:
ПДА по условию соответствия измерений (например, ЛицевойСчет).Период регистра должен быть меньше или равен Событие.Дата.Если объем данных велик, прямое соединение с физической таблицей может привести к деградации производительности. В этом случае мы рекомендуем использовать временные таблицы:
Такой подход позволяет оптимизатору СУБД построить план выполнения запроса, используя индексы, что критически важно для быстродействия системы.
При сравнении дат документов и дат в регистре сведений часто возникает вопрос: нужно ли хранить время? Рассмотрим важные аспекты:
Дата в 1С всегда занимает 8 байт, вне зависимости от того, есть в ней время или только дата (в последнем случае время просто равно 00:00:00). Добавление времени не увеличит размер хранения данных, но может повлиять на размер индексов.НАЧАЛОПЕРИОДА() или КОНЕЦПЕРИОДА().Важное предостережение: Никогда не сравнивайте поле с временем и поле без времени напрямую, так как это препятствует использованию индексов (индекс перестает быть SARGable). Это приводит к полному сканированию таблицы (Table Scan), что на больших объемах данных «подвесит» вашу систему.
Рассмотрим структуру запроса, который находит срез последних на дату документа:
ВЫБРАТЬ
Событие.ЛицевойСчет КАК ЛицевойСчет,
Событие.Дата КАК ДатаСобытия,
МаксПериод.МаксДата
ПОМЕСТИТЬ ВТ_МаксДаты
ИЗ Документ.Событие КАК Событие
ЛЕВОЕ СОЕДИНЕНИЕ (
ВЫБРАТЬ
ПДА.ЛицевойСчет КАК ЛицевойСчет,
МАКСИМУМ(ПДА.Период) КАК МаксДата
ИЗ РегистрСведений.ПДА КАК ПДА
ГРУППИРОВАТЬ ПО ПДА.ЛицевойСчет
) КАК МаксПериод ПО Событие.ЛицевойСчет = МаксПериод.ЛицевойСчет
И Событие.Дата >= МаксПериод.МаксДата
;
ВЫБРАТЬ
ВТ_МаксДаты.ЛицевойСчет,
ПДА.ДатаАктуальности
ИЗ ВТ_МаксДаты
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПДА КАК ПДА
ПО ВТ_МаксДаты.ЛицевойСчет = ПДА.ЛицевойСчет
И ВТ_МаксДаты.МаксДата = ПДА.Период
Использование этого подхода позволит вам точно сопоставить дату события и соответствующий срез регистра, обеспечив при этом высокую скорость работы запроса даже при значительном росте базы данных.