Как обойти ограничение 1С:Фреш на использование подзапросов в запросе динамического списка?

Программист 1С v8.3 (Управляемые формы) Управленческий учет Торговля и дистрибуция
← На главную

В работе с динамическими списками в 1С:Предприятии, особенно в облачном сервисе 1С:Фреш, мы часто сталкиваемся с необходимостью отображения комплексных данных, которые требуют выполнения сложных запросов. Однако использование подзапросов в таких запросах может привести к снижению производительности и отклонению доработок аудитом 1С:Фреш. Рассмотрим ситуацию, когда возникла такая проблема, и предложим оптимальные пути ее решения.

Анализируем проблему: подзапрос в динамическом списке и ограничения 1С:Фреш

Предположим, у нас есть динамический список документов РасходнаяНакладная, и нам необходимо отобразить в нем дату самого раннего или самого позднего заказа, связанного с элементами табличной части этого документа. Для решения этой задачи интуитивно мы можем создать подзапрос, который агрегирует данные из табличной части Запасы документа.

Изначальный запрос, который был отклонен 1С:Фреш, выглядел следующим образом:


ВЫБРАТЬ
    ВЫБОР
        КОГДА ДокументРасходнаяНакладная.СуммаДокумента > 0
            ТОГДА ВЫБОР
                    КОГДА НЕ ДокументРасходнаяНакладная.Контрагент.ВестиРасчетыПоДокументам
                            ИЛИ ФактОплаты.Сумма ЕСТЬ NULL
                        ТОГДА -1
                    КОГДА ЕСТЬNULL(ФактОплаты.СуммаОплаты, 0) + ЕСТЬNULL(ФактОплаты.СуммаАванса, 0) = 0
                        ТОГДА 2
                    КОГДА ЕСТЬNULL(ФактОплаты.СуммаОплаты, 0) + ЕСТЬNULL(ФактОплаты.СуммаАванса, 0) = ДокументРасходнаяНакладная.СуммаДокумента
                        ТОГДА 0
                    КОГДА ЕСТЬNULL(ФактОплаты.СуммаОплаты, 0) + ЕСТЬNULL(ФактОплаты.СуммаАванса, 0) > ДокументРасходнаяНакладная.СуммаДокумента
                        ТОГДА 7
                    ИНАЧЕ 1
                КОНЕЦ
        ИНАЧЕ -1
    КОНЕЦ КАК НомерКартинкиОплаты,
    ВЫБОР
        КОГДА ДокументРасходнаяНакладная.СуммаДокумента > 0
            ТОГДА ВЫБОР
                    КОГДА ФактОплаты.Сумма ЕСТЬ NULL
                        ТОГДА "Не учитывается"
                    КОГДА ЕСТЬNULL(ФактОплаты.СуммаОплаты, 0) + ЕСТЬNULL(ФактОплаты.СуммаАванса, 0) - ДокументРасходнаяНакладная.СуммаДокумента >= 0
                        ТОГДА "Оплачен полностью"
                    КОГДА ЕСТЬNULL(ФактОплаты.СуммаОплаты, 0) + ЕСТЬNULL(ФактОплаты.СуммаАванса, 0) > 0
                        ТОГДА "Оплачен частично"
                    ИНАЧЕ "Без оплаты"
                КОНЕЦ
        ИНАЧЕ "Не учитывается"
    КОНЕЦ КАК СтатусОплаты,
    ЕСТЬNULL(ФактОплаты.Сумма, 0) - ЕСТЬNULL(ФактОплаты.СуммаОплаты, 0) - ЕСТЬNULL(ФактОплаты.СуммаАванса, 0) КАК КОплате,
    ВЫБОР
        КОГДА ДокументРасходнаяНакладная.Проведен
                И ДокументРасходнаяНакладная.СуммаДокумента > 0
            ТОГДА ВЫРАЗИТЬ((ЕСТЬNULL(ФактОплаты.СуммаОплаты, 0) + ЕСТЬNULL(ФактОплаты.СуммаАванса, 0)) * 100 / ДокументРасходнаяНакладная.СуммаДокумента КАК ЧИСЛО(15, 2))
        ИНАЧЕ 0
    КОНЕЦ КАК ПроцентОплаты,
    ДокументРасходнаяНакладная.Ссылка КАК Ссылка,
    ДокументРасходнаяНакладная.ПометкаУдаления КАК ПометкаУдаления,
    ДокументРасходнаяНакладная.Номер КАК Номер,
    ДокументРасходнаяНакладная.Дата КАК Дата,
    ДокументРасходнаяНакладная.Проведен КАК Проведен,
    ДокументРасходнаяНакладная.Автомобиль КАК Автомобиль,
    ДокументРасходнаяНакладная.Автор КАК Автор,
    ДокументРасходнаяНакладная.АдресДоставки КАК АдресДоставки,
    ДокументРасходнаяНакладная.БанковскийСчет КАК БанковскийСчет,
    ДокументРасходнаяНакладная.БанковскийСчетКонтрагента КАК БанковскийСчетКонтрагента,
    ДокументРасходнаяНакладная.БанковскийСчетПеревозчика КАК БанковскийСчетПеревозчика,
    ДокументРасходнаяНакладная.ВалютаДокумента КАК ВалютаДокумента,
    ДокументРасходнаяНакладная.ВидОперации КАК ВидОперации,
    ДокументРасходнаяНакладная.ВидСкидкиНаценки КАК ВидСкидкиНаценки,
    ДокументРасходнаяНакладная.ВидЦен КАК ВидЦен,
    ДокументРасходнаяНакладная.Водитель КАК Водитель,
    ДокументРасходнаяНакладная.Грузоотправитель КАК Грузоотправитель,
    ДокументРасходнаяНакладная.Грузополучатель КАК Грузополучатель,
    ДокументРасходнаяНакладная.ДатаВходящегоДокумента КАК ДатаВходящегоДокумента,
    ДокументРасходнаяНакладная.ДоверенностьВыдана КАК ДоверенностьВыдана,
    ДокументРасходнаяНакладная.ДоверенностьДата КАК ДоверенностьДата,
    ДокументРасходнаяНакладная.ДоверенностьЛицо КАК ДоверенностьЛицо,
    ДокументРасходнаяНакладная.ДоверенностьНомер КАК ДоверенностьНомер,
    ДокументРасходнаяНакладная.Договор КАК Договор,
    ДокументРасходнаяНакладная.ДокументОснование КАК ДокументОснование,
    ДокументРасходнаяНакладная.Заказ КАК Заказ,
    ДокументРасходнаяНакладная.Комментарий КАК Комментарий,
    ДокументРасходнаяНакладная.Контрагент КАК Контрагент,
    ДокументРасходнаяНакладная.Кратность КАК Кратность,
    ДокументРасходнаяНакладная.Курс КАК Курс,
    ДокументРасходнаяНакладная.НалогообложениеНДС КАК НалогообложениеНДС,
    ДокументРасходнаяНакладная.НДСВключатьВСтоимость КАК НДСВключатьВСтоимость,
    ДокументРасходнаяНакладная.НомерВходящегоДокумента КАК НомерВходящегоДокумента,
    ДокументРасходнаяНакладная.Организация КАК Организация,
    ДокументРасходнаяНакладная.ОснованиеПечати КАК ОснованиеПечати,
    ДокументРасходнаяНакладная.Ответственный КАК Ответственный,
    ДокументРасходнаяНакладная.Перевозчик КАК Перевозчик,
    ДокументРасходнаяНакладная.Подразделение КАК Подразделение,
    ДокументРасходнаяНакладная.ПоложениеЗаказаПокупателя КАК ПоложениеЗаказаПокупателя,
    ДокументРасходнаяНакладная.Прицеп КАК Прицеп,
    ДокументРасходнаяНакладная.СрокДоставки КАК СрокДоставки,
    ДокументРасходнаяНакладная.СтруктурнаяЕдиница КАК СтруктурнаяЕдиница,
    ДокументРасходнаяНакладная.СуммаВключаетНДС КАК СуммаВключаетНДС,
    ДокументРасходнаяНакладная.СуммаДокумента КАК СуммаДокумента,
    ДокументРасходнаяНакладная.Ячейка КАК Ячейка,
    ДокументРасходнаяНакладная.ДисконтнаяКарта КАК ДисконтнаяКарта,
    ДокументРасходнаяНакладная.ПроцентСкидкиПоДисконтнойКарте КАК ПроцентСкидкиПоДисконтнойКарте,
    ДокументРасходнаяНакладная.СкидкиРассчитаны КАК СкидкиРассчитаны,
    ДокументРасходнаяНакладная.ХозяйственнаяОперация КАК ХозяйственнаяОперация,
    ДокументРасходнаяНакладная.ВидЭлектронногоДокумента КАК ВидЭлектронногоДокумента,
    ДокументРасходнаяНакладная.Запасы.(
        Ссылка КАК Ссылка,
        НомерСтроки КАК НомерСтроки,
        Номенклатура КАК Номенклатура,
        Партия КАК Партия,
        ТипНоменклатурыЗапас КАК ТипНоменклатурыЗапас,
        Резерв КАК Резерв,
        СерииНоменклатуры КАК СерииНоменклатуры,
        ЕдиницаИзмерения КАК ЕдиницаИзмерения,
        Цена КАК Цена,
        ПроцентСкидкиНаценки КАК ПроцентСкидкиНаценки,
        СуммаСкидкиНаценки КАК СуммаСкидкиНаценки,
        Сумма КАК Сумма,
        СтавкаНДС КАК СтавкаНДС,
        СуммаНДС КАК СуммаНДС,
        Всего КАК Всего,
        Заказ КАК Заказ,
        Содержание КАК Содержание,
        ПроцентАвтоматическойСкидки КАК ПроцентАвтоматическойСкидки,
        СуммаАвтоматическойСкидки КАК СуммаАвтоматическойСкидки,
        КлючСвязи КАК КлючСвязи,
        Характеристика КАК Характеристика,
        УдалитьСправкаБ КАК УдалитьСправкаБ,
        Количество КАК Количество,
        СтранаПроисхождения КАК СтранаПроисхождения,
        НомерГТД КАК НомерГТД,
        ТоварыДляПроизводства КАК ТоварыДляПроизводства,
        Вес КАК Вес,
        Объем КАК Объем,
        СтруктурнаяЕдиница КАК СтруктурнаяЕдиница,
        Ячейка КАК Ячейка,
        НоменклатураНабора КАК НоменклатураНабора,
        ХарактеристикаНабора КАК ХарактеристикаНабора,
        ДоляСтоимости КАК ДоляСтоимости
    ) КАК Запасы,
    ДокументРасходнаяНакладная.Предоплата.(
        Ссылка КАК Ссылка,
        НомерСтроки КАК НомерСтроки,
        Документ КАК Документ,
        НомерСертификата КАК НомерСертификата,
        Заказ КАК Заказ,
        СуммаРасчетов КАК СуммаРасчетов,
        Курс КАК Курс,
        Кратность КАК Кратность,
        СуммаПлатежа КАК СуммаПлатежа,
        ОплатаСертификатом КАК ОплатаСертификатом
    ) КАК Предоплата,
    ДокументРасходнаяНакладная.ДополнительныеРеквизиты.(
        Ссылка КАК Ссылка,
        НомерСтроки КАК НомерСтроки,
        Свойство КАК Свойство,
        Значение КАК Значение,
        ТекстоваяСтрока КАК ТекстоваяСтрока
    ) КАК ДополнительныеРеквизиты,
    ДокументРасходнаяНакладная.СкидкиНаценки.(
        Ссылка КАК Ссылка,
        НомерСтроки КАК НомерСтроки,
        КлючСвязи КАК КлючСвязи,
        СкидкаНаценка КАК СкидкаНаценка,
        Сумма КАК Сумма
    ) КАК СкидкиНаценки,
    ДокументРасходнаяНакладная.МоментВремени КАК МоментВремени,
    СостоянияЭД.СостояниеЭДО КАК СостояниеВерсииЭД,
    ВЫБОР
        КОГДА НаличиеФайлов.ЕстьФайлы ЕСТЬ NULL
            ТОГДА 0
        КОГДА НаличиеФайлов.ЕстьФайлы
            ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ КАК ЕстьФайлы,
    NULL КАК СостояниеОригиналаПервичногоДокумента,
    ИСТИНА КАК ОбщееСостояние,
    0 КАК СостояниеОригиналПолучен,
    ЕСТЬNULL(СостоянияОригиналовПервичныхДокументов.Состояние, ЗНАЧЕНИЕ(Справочник.СостоянияОригиналовПервичныхДокументов.ПустаяСсылка)) КАК СостояниеОригинала
ИЗ
    Документ.РасходнаяНакладная КАК ДокументРасходнаяНакладная
    {ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
            Т.Ссылка КАК Ссылка,
            МАКСИМУМ(НАЧАЛОПЕРИОДА(Т.Заказ.Дата, ДЕНЬ)) КАК ДатаЗаказа
        ИЗ
            Документ.РасходнаяНакладная.Запасы КАК Т
        
        СГРУППИРОВАТЬ ПО
            Т.Ссылка) КАК ЗаказыПокупателя
    ПО (ЗаказыПокупателя.Ссылка = ДокументРасходнаяНакладная.Ссылка)}
    {ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СостоянияПоОбъектамУчетаЭДО КАК СостоянияЭД
    ПО (СостоянияЭД.СсылкаНаОбъект = ДокументРасходнаяНакладная.Ссылка)}
    {ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ФактОплатыДокументов КАК ФактОплаты
    ПО ДокументРасходнаяНакладная.Ссылка = ФактОплаты.Документ}
    {ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.НаличиеФайлов КАК НаличиеФайлов
    ПО ДокументРасходнаяНакладная.Ссылка = НаличиеФайлов.ОбъектСФайлами}
    {ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СостоянияОригиналовПервичныхДокументов КАК СостоянияОригиналовПервичныхДокументов
    ПО ДокументРасходнаяНакладная.Ссылка = СостоянияОригиналовПервичныхДокументов.Владелец
        И (СостоянияОригиналовПервичныхДокументов.ОбщееСостояние = ИСТИНА)}

Конкретным проблемным местом в этом запросе является следующий подзапрос, который выполняет агрегацию по табличной части Запасы:


{ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
        Т.Ссылка КАК Ссылка,
        МАКСИМУМ(НАЧАЛОПЕРИОДА(Т.Заказ.Дата, ДЕНЬ)) КАК ДатаЗаказа
    ИЗ
        Документ.РасходнаяНакладная.Запасы КАК Т
    
    СГРУППИРОВАТЬ ПО
        Т.Ссылка) КАК ЗаказыПокупателя
ПО (ЗаказыПокупателя.Ссылка = ДокументРасходнаяНакладная.Ссылка)}

1С:Фреш отклоняет такие конструкции, выдавая замечание о чрезмерной нагрузке на компоненты сервиса и неоптимальной работе запроса, рекомендуя использовать временные таблицы или пересмотреть подход. Аудит 1С ссылается на документацию по оптимизации запросов, например, на информацию, доступную на ИТС. Разберем, почему возникают такие ограничения и как их эффективно обойти.

Почему подзапросы не рекомендуются в динамических списках 1С (особенно в 1С:Фреш)?

Прежде чем перейти к решениям, давайте выясним причины, по которым сложные подзапросы, особенно агрегирующие данные из табличных частей, нежелательны в динамических списках:

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

  2. Механизм порционного считывания (пейджинг). Платформа 1С оптимизирует запросы динамических списков, добавляя секции ПЕРВЫЕ N (выборка первых N записей), условия для граничных ссылок и сортировки, чтобы загружать данные порциями (обычно по 45 строк). Подзапросы могут нарушать или затруднять этот механизм, заставляя платформу выполнять более объемные запросы или даже полностью считывать данные для каждой порции, что приводит к значительным задержкам.

  3. Нагрузка на СУБД. Многократное выполнение сложного запроса с подзапросами при прокрутке списка, изменении отбора или сортировки создает высокую нагрузку на СУБД. Это особенно критично в многопользовательских и облачных системах типа 1С:Фреш, где важна общая производительность сервиса и стабильность работы для множества клиентов.

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

Оптимальные решения для обхода ограничений 1С:Фреш

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

1. Предварительный расчет и хранение данных в реквизите документа (решение автора)

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

В нашем случае, для получения максимальной даты заказа из табличной части, мы можем добавить дополнительный реквизит в документ РасходнаяНакладная и заполнять его при записи документа.

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

  2. Реализуйте заполнение реквизита в обработчике события. Для документа РасходнаяНакладная создайте или модифицируйте обработчик события ПередЗаписью на стороне сервера. В этом обработчике мы будем перебирать строки табличной части Запасы и находить ссылку на заказ с максимальной датой, присваивая её новому реквизиту дор_Заказ.

    Пример кода для обработчика ПередЗаписью, адаптированный для поиска ссылки на заказ с максимальной датой:

    
    &После("ПередЗаписью")
    Процедура мл_ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
        // Инициализируем реквизит для хранения ссылки на заказ с максимальной датой
        // Предполагаем, что дор_Заказ имеет тип ДокументСсылка.ЗаказПокупателя
        ЭтотОбъект.дор_Заказ = Неопределено;
        ДатаМаксимальногоЗаказа = '00010101'; // Минимальная дата для начального сравнения
    
        Для Каждого Строка ИЗ ЭтотОбъект.Запасы Цикл
            Если ЗначениеЗаполнено(Строка.Заказ) Тогда
                // Проверяем, существует ли заказ и его дата больше текущей максимальной даты
                Если Строка.Заказ.Дата > ДатаМаксимальногоЗаказа Тогда
                    ДатаМаксимальногоЗаказа = Строка.Заказ.Дата;
                    ЭтотОбъект.дор_Заказ = Строка.Заказ;
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
    КонецПроцедуры
    

    Важно: Данный код обеспечивает поиск именно последнего (по дате) заказа из табличной части Запасы документа РасходнаяНакладная. Он соответствует логике агрегации МАКСИМУМ(НАЧАЛОПЕРИОДА(Т.Заказ.Дата, ДЕНЬ)) из исходного запроса.

  3. Используйте новый реквизит в запросе динамического списка. После того как реквизит дор_Заказ будет заполняться при записи документа, вы сможете просто добавить его в список выбираемых полей основного запроса динамического списка. Это устранит необходимость в сложном подзапросе и дополнительном соединении с табличной частью.

    Модифицированный фрагмент запроса будет выглядеть значительно проще:

    
    ВЫБРАТЬ
        ДокументРасходнаяНакладная.дор_Заказ КАК ЗаказДокумента,
        // ... другие поля
    ИЗ
        Документ.РасходнаяНакладная КАК ДокументРасходнаяНакладная
        // ... далее идут другие соединения, если они необходимы и оптимизированы
    

Преимущества данного подхода:

2. Использование вспомогательных регистров сведений для хранения агрегированных данных

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

  1. Создайте вспомогательный регистр сведений. Например, можно создать регистр сведений АгрегированныеДанныеРасходныхНакладных. В этом регистре должны быть измерения, идентифицирующие документ (например, Документ с типом ДокументСсылка.РасходнаяНакладная) и ресурсы для хранения рассчитанных значений (например, МаксимальнаяДатаЗаказа с типом Дата, или СсылкаНаМаксимальныйЗаказ с типом ДокументСсылка.ЗаказПокупателя).

  2. Организуйте расчет и запись данных. Это можно сделать несколькими способами:

    • В обработчиках проведения документов (если данные зависят от проведения) или при записи документов (аналогично предыдущему способу, но вместо реквизита документа записываем данные в регистр сведений).

    • С помощью регламентных заданий, которые периодически обходят документы и рассчитывают необходимые значения, записывая их в регистр. Это позволяет распределить нагрузку во времени и не замедлять интерактивную работу пользователя.

  3. Используйте регистр в запросе динамического списка. В запросе динамического списка вам останется только выполнить левое соединение с этим вспомогательным регистром. Это будет простой и быстрый запрос:

    
    ВЫБРАТЬ
        ДокументРасходнаяНакладная.Ссылка,
        // ... другие поля
        ЕСТЬNULL(ВспомогательныйРегистр.СсылкаНаМаксимальныйЗаказ, ЗНАЧЕНИЕ(Документ.ЗаказПокупателя.ПустаяСсылка)) КАК МаксимальныйЗаказ
    ИЗ
        Документ.РасходнаяНакладная КАК ДокументРасходнаяНакладная
            ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.АгрегированныеДанныеРасходныхНакладных КАК ВспомогательныйРегистр
            ПО ДокументРасходнаяНакладная.Ссылка = ВспомогательныйРегистр.Документ
    

    Этот подход обеспечивает высокую гибкость и позволяет эффективно управлять актуальностью данных, перемещая тяжелые вычисления в фоновые процессы.

3. Использование обработчика "ПриПолученииДанныхНаСервере" (для некритичных данных)

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

  1. В основном запросе динамического списка мы не включаем эти вспомогательные поля.

  2. В обработчике ПриПолученииДанныхНаСервере мы получаем коллекцию всех отображаемых строк, которая передается в этот обработчик после выполнения основного запроса динамического списка.

  3. Мы формируем список ссылок на документы из этой коллекции строк.

  4. Одним запросом выбираем необходимые вспомогательные данные для всех этих строк, используя их ссылки как параметры запроса (например, в условии ГДЕ Ссылка В (&СписокСсылок)).

  5. Перебираем полученные данные и заполняем их в соответствующие колонки динамического списка.

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

4. Временные таблицы в динамических списках: нюансы и ограничения

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

Временные таблицы могут быть полезны для подготовки промежуточных данных внутри сложного пакетного запроса. Например, мы можем сначала собрать необходимые ссылки или агрегированные данные во временную таблицу, а затем соединить её с основной таблицей динамического списка. Это позволяет разбить сложный запрос на более простые шаги и потенциально использовать индексы.

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

Таким образом, хотя временные таблицы и поддерживаются, их следует использовать осторожно. Необходимо избегать ситуаций, когда основная выборка динамического списка полностью основывается на временной таблице. В большинстве случаев для 1С:Фреш предварительный расчет и хранение данных в реквизитах или регистрах будет более оптимальным решением, чем попытка построить сложный пакетный запрос с временными таблицами в динамическом списке.

Заключение

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

← На главную