Доброго дня, коллеги!
Использование виртуальных таблиц в запросах – базовый навык специалиста 1С. В рамках курса Разработка и оптимизация запросов в 1С:Предприятие 8.3 виртуальные таблицы изучаются вдоль и поперек:)
Стратегия расчета остатков с использованием таблиц итогов на “будущую” дату и таблиц движений не всем слушателям кажется логичной, но с разработчиками 1С не поспоришь!
Вопрос
Если взять пример из курса и поменять в нем только саму дату среза итогов на 05.03.2012. Разве оптимизатор не предпочтет выбрать итоги на 01.03.2012, а потом прибавить к ним выборку из таблицы движений за период с 01.03.2012 по 04.03.2012 23:59:59.
Ответ
Добрый день! Это достаточно логичное пожелание, которое часто встречается, но платформа так не поступает. Посмотрим при помощи консоли, какой запрос используется для получения остатков на 05.03.2012:
SELECT T1.Fld82RRef, T1.Fld83RRef, T1.Fld84Balance_ FROM (SELECT T2.Fld82RRef AS Fld82RRef, T2.Fld83RRef AS Fld83RRef, SUM(T2.Fld84Balance_) AS Fld84Balance_ FROM (SELECT T3._Fld82RRef AS Fld82RRef, T3._Fld83RRef AS Fld83RRef, SUM(T3._Fld84) AS Fld84Balance_ FROM _AccumRgT85 T3 WHERE T3._Period = {ts '2012-04-01 00:00:00'} AND ((T3._Fld83RRef = 0xA9B000055D49B45E11DB8B8BEE7616E1)) AND (T3._Fld84 <> 0) AND (T3._Fld84 <> 0) GROUP BY T3._Fld82RRef, T3._Fld83RRef HAVING (SUM(T3._Fld84)) <> 0 UNION ALL SELECT T4._Fld82RRef AS Fld82RRef, T4._Fld83RRef AS Fld83RRef, CAST(SUM(CASE WHEN T4._RecordKind = 0 THEN -T4._Fld84 ELSE T4._Fld84 END) AS NUMERIC(22, 2)) AS Fld84Balance_ FROM _AccumRg81 T4 WHERE T4._Period >= {ts '2012-03-05 00:00:00'} AND T4._Period < {ts '2012-04-01 00:00:00'} AND T4._Active = TRUE AND ((T4._Fld83RRef = 0xA9B000055D49B45E11DB8B8BEE7616E1)) GROUP BY T4._Fld82RRef, T4._Fld83RRef HAVING (CAST(SUM(CASE WHEN T4._RecordKind = 0 THEN -T4._Fld84 ELSE T4._Fld84 END) AS NUMERIC(22, 2))) <> 0) T2 GROUP BY T2.Fld82RRef, T2.Fld83RRef HAVING (SUM(T2.Fld84Balance_)) <> 0) T1
Видно, что получаются итоги на 01.04.2012, а не на 01.03.2012.
Предполагаю, в общем случае сложно определить, что будет оптимальнее:
- получить итоги на предыдущий месяц и скорректировать их по таблице движений
- получить итоги на следующий месяц и скорректировать их по таблице движений
Поэтому платформа всегда получает итоги на “будущую” дату.
Теперь в запросе установим значение периода на 05.03.2019. Здесь уже платформа будет использовать актуальные (текущие) итоги, которые хранятся в базе на дату 01.11.3999:
SELECT T1.Fld82RRef, T1.Fld83RRef, T1.Fld84Balance_ FROM (SELECT T2.Fld82RRef AS Fld82RRef, T2.Fld83RRef AS Fld83RRef, SUM(T2.Fld84Balance_) AS Fld84Balance_ FROM (SELECT T3._Fld82RRef AS Fld82RRef, T3._Fld83RRef AS Fld83RRef, SUM(T3._Fld84) AS Fld84Balance_ FROM _AccumRgT85 T3 WHERE T3._Period = {ts '3999-11-01 00:00:00'} AND ((T3._Fld83RRef = 0xA9B000055D49B45E11DB8B8BEE7616E1)) AND (T3._Fld84 <> 0) AND (T3._Fld84 <> 0) GROUP BY T3._Fld82RRef, T3._Fld83RRef HAVING (SUM(T3._Fld84)) <> 0 UNION ALL SELECT T4._Fld82RRef AS Fld82RRef, T4._Fld83RRef AS Fld83RRef, CAST(SUM(CASE WHEN T4._RecordKind = 0 THEN -T4._Fld84 ELSE T4._Fld84 END) AS NUMERIC(22, 2)) AS Fld84Balance_ FROM _AccumRg81 T4 WHERE T4._Period >= {ts '2019-03-05 00:00:00'} AND T4._Period < {ts '3999-11-01 00:00:00'} AND T4._Active = TRUE AND ((T4._Fld83RRef = 0xA9B000055D49B45E11DB8B8BEE7616E1)) GROUP BY T4._Fld82RRef, T4._Fld83RRef HAVING (CAST(SUM(CASE WHEN T4._RecordKind = 0 THEN -T4._Fld84 ELSE T4._Fld84 END) AS NUMERIC(22, 2))) <> 0) T2 GROUP BY T2.Fld82RRef, T2.Fld83RRef HAVING (SUM(T2.Fld84Balance_)) <> 0) T1
Почему именно так происходит? Потому что это ближайшие итоги в будущем от даты, на которую требуется получить остатки. В документации на ИТС есть подтверждение такого поведения платформы – статья Устройство регистра накопления. В статье сказано: Подбирается ближайший больший или равный момент времени, на который рассчитаны остатки. Вот так и ведет себя платформа при получении остатков.
P.S.
Понимать, как работают запросы и уметь их строить - обязательный навык для всех, кто дорабатывает и внедряет 1С.
После курса Вы сможете:
- Строить сложные запросы с несколькими источниками данных
- Уверенно задействовать вложенные запросы и временные таблицы
- Использовать встроенный язык для обработки результатов запроса
- Учитывать особенности соединений и объединений нескольких таблиц.
- Разрабатывать запросы на уровне задач Аттестации 1С:Специалист по платформе.