Как оптимизировать запрос к документам и настроить отбор по связанным справочникам в 1С

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

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

Постановка задачи и первая проблема

Представим ситуацию: нам нужно получить данные о возврате тары (ящиков) из документа ВозвратТоваровОтПокупателя. В документе есть реквизит Водитель, который имеет тип СправочникСсылка.ФизическиеЛица. Однако нам нужны только те водители, которые зарегистрированы в специализированном справочнике уатСотрудники (из отраслевого решения «Управление автотранспортом»).

Разберем, как связать эти таблицы, если прямой ссылки из документа на справочник сотрудников нет, но в самом справочнике сотрудников есть реквизит ФизЛицо.

Решение 1: Связывание через внутреннее соединение

Самый правильный способ отсечь лишние записи — использовать ВНУТРЕННЕЕ СОЕДИНЕНИЕ. Это позволит оставить в выборке только те документы, водители которых найдены в справочнике уатСотрудники. Проанализируем правильный синтаксис условия связи:


ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.уатСотрудники КАК уатСотрудники
ПО ВозвратТоваровОтПокупателя.Водитель = уатСотрудники.ФизЛицо

Важно помнить: мы сравниваем ссылку на физическое лицо из документа с реквизитом ФизЛицо справочника сотрудников. Использование ВНУТРЕННЕЕ СОЕДИНЕНИЕ автоматически работает как фильтр (отбор).

Решение 2: Оптимизация запроса и отказ от «точек»

Одной из главных причин низкой производительности и ошибок памяти является обращение к полям через точку (например, ТабличнаяЧасть.Ссылка.Дата или ТабличнаяЧасть.Ссылка.Водитель.Наименование). В терминах SQL каждое такое обращение порождает неявное левое соединение с соответствующей таблицей. Если документ содержит тысячи строк, количество соединений становится критическим.

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


ВЫБРАТЬ
    ВозвратТара.Номенклатура КАК НаименованиеЯщика,
    ВозвратТара.Количество,
    Возврат.Водитель КАК ФИОВодителя
ИЗ
    Документ.ВозвратТоваровОтПокупателя КАК Возврат
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.уатСотрудники КАК уатСотрудники
        ПО Возврат.Водитель = уатСотрудники.ФизЛицо
        
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ВозвратТоваровОтПокупателя.ВозвратнаяТара КАК ВозвратТара
        ПО ВозвратТара.Ссылка = Возврат.Ссылка
ГДЕ
    Возврат.Проведен
    И Возврат.Дата МЕЖДУ &ДатаНачало И &ДатаКонец

Почему это работает лучше? Мы сначала фильтруем шапки документов (по дате и проведению), затем отсекаем их по наличию сотрудника, и только к отфильтрованным заголовкам «цепляем» строки табличной части. Это значительно сокращает объем обрабатываемых данных.

Решение 3: Использование временных таблиц для борьбы с нехваткой памяти

Если документов за период очень много, даже оптимизированное соединение может «повесить» систему. В таких случаях мы рекомендуем использовать временные таблицы. Сначала мы выберем во временную таблицу список подходящих сотрудников, а затем используем её для основного запроса.

Рассмотрим этот мощный механизм подробнее:


// Шаг 1: Отбираем нужных водителей во временную таблицу
ВЫБРАТЬ
    уатСотрудники.ФизЛицо КАК ФизЛицо
ПОМЕСТИТЬ ВТ_Водители
ИЗ
    Справочник.уатСотрудники КАК уатСотрудники;

// Шаг 2: Выбираем только нужные документы
ВЫБРАТЬ
    Возврат.Ссылка КАК Ссылка,
    Возврат.Водитель КАК Водитель
ПОМЕСТИТЬ ВТ_Документы
ИЗ
    Документ.ВозвратТоваровОтПокупателя КАК Возврат
ГДЕ
    Возврат.Проведен
    И Возврат.Дата МЕЖДУ &ДатаНачало И &ДатаКонец
    И Возврат.Водитель В (ВЫБРАТЬ ФизЛицо ИЗ ВТ_Водители);

// Шаг 3: Финальная выборка данных из ТЧ отобранных документов
ВЫБРАТЬ
    ВТ_Документы.Водитель КАК ФИОВодителя,
    ВозвратТара.Номенклатура,
    ВозвратТара.Количество
ИЗ
    ВТ_Документы КАК ВТ_Документы
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ВозвратТоваровОтПокупателя.ВозвратнаяТара КАК ВозвратТара
        ПО ВозвратТара.Ссылка = ВТ_Документы.Ссылка

Такой подход минимизирует нагрузку на оперативную память, так как СУБД работает с небольшими индексированными наборами данных вместо одной гигантской таблицы.

Дополнительные приемы работы с запросами

В процессе работы часто возникают сопутствующие вопросы. Разберем два наиболее важных.

Как проверить заполненность ссылки в запросе?

Если в условии ГДЕ нужно отсечь документы, в которых водитель не указан, используйте сравнение с пустой ссылкой конкретного типа. Рассмотрим пример:

ГДЕ Возврат.Водитель <> ЗНАЧЕНИЕ(Справочник.ФизическиеЛица.ПустаяСсылка)

Это работает быстрее, чем проверка на NULL, и гарантирует корректность типов в базе данных.

Как исключить документы, на основании которых созданы другие документы?

Допустим, нам нужно вывести только те Реализации, по которым еще не было сделано Возвратов. Самый надежный способ — использовать ЛЕВОЕ СОЕДИНЕНИЕ и проверку на отсутствие записи во второй таблице.

Выясним, как это выглядит в коде:


ВЫБРАТЬ
    Реализация.Ссылка
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.ВозвратТоваровОтПокупателя КАК Возврат
        ПО Возврат.ДокументОснование = Реализация.Ссылка
ГДЕ
    Возврат.Ссылка ЕСТЬ NULL

Важный момент: если в поле Ссылка таблицы Возврат стоит NULL, это означает, что соединение не нашло соответствующей записи. Следовательно, возврата по этой реализации не существует.

Заключение

Мы проанализировали основные методы оптимизации запросов в 1С при работе с табличными частями и сложными отборами. Подведем итог: всегда старайтесь избегать обращений через точку к ссылочным полям в условиях и полях выборки, используйте явные соединения (JOIN) и не бойтесь применять временные таблицы. Это обеспечит стабильную работу ваших отчетов даже на очень больших объемах данных.

← На главную