Как соединить таблицы регистров в запросе 1С для фильтрации определенных типов документов

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

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

Постановка задачи

Представим ситуацию: у нас есть два регистра накопления — Продажи и РасчетыСПокупателями. В регистре Продажи фиксируются движения по документам РеализацияТоваровУслуг и ОтчетОРозничныхПродажах. В регистре РасчетыСПокупателями отражаются только Реализации. Нам необходимо получить итоговую таблицу, в которую войдут:

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

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

Решение через использование конструкции ОБЪЕДИНИТЬ ВСЕ

Проанализируем подход, который является наиболее стабильным с точки зрения логики и производительности. Вместо того чтобы пытаться построить одно сложное соединение с условиями ИЛИ в блоке ГДЕ, мы разделим задачу на части и объединим результаты.

Рассмотрим пример кода запроса, который реализует эту логику:


ВЫБРАТЬ
    Продажи.Регистратор КАК Регистратор,
    Продажи.СуммаОборот КАК Сумма
ИЗ
    РегистрНакопления.Продажи.Обороты КАК Продажи
ГДЕ
    Продажи.Регистратор ССЫЛКА Документ.ОтчетОРозничныхПродажах

ОБЪЕДИНИТЬ ВСЕ

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

В первой части запроса мы выбираем все Отчеты о розничных продажах. Во второй части мы выбираем только те Реализации, которые входят в список регистраторов регистра РасчетыСПокупателями. Использование оператора ОБЪЕДИНИТЬ ВСЕ позволяет СУБД выполнить два простых поиска вместо одного сложного соединения, что положительно сказывается на скорости выполнения.

Оптимизация с использованием временных таблиц

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

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

Проанализируем структуру такого запроса:


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

// Шаг 2: Получаем итоговый результат
ВЫБРАТЬ
    Продажи.Регистратор
ИЗ
    РегистрНакопления.Продажи КАК Продажи
ГДЕ
    Продажи.Регистратор ССЫЛКА Документ.ОтчетОРозничныхПродажах

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Продажи.Регистратор
ИЗ
    РегистрНакопления.Продажи КАК Продажи
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_РеализацииВРасчетах КАК ВТ_Реализации
    ПО Продажи.Регистратор = ВТ_Реализации.Документ

Почему сложные соединения — это «зло»?

Выясним причину, по которой опытные разработчики предостерегают от прямых соединений физических таблиц разных регистров. Когда вы соединяете две таблицы по полю Регистратор, СУБД приходится сравнивать значения составных типов. Если в условии соединения или фильтрации появляется ИЛИ (например, ГДЕ Тип = Отчет ИЛИ (Тип = Реализация И НаличиеВРасчетах)), оптимизатор запросов SQL может отказаться от использования индексов и перейти к полному сканированию таблиц (Table Scan). Это приведет к тому, что отчет, который должен формироваться секунды, будет работать минуты.

Важные нюансы при работе с регистрами

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

Таким образом, разделение сложной логики на простые блоки через временные таблицы и объединения — это залог надежного и быстрого кода в 1С.

← На главную