Что лучше использовать в запросах 1С: ЛЕВОЕ СОЕДИНЕНИЕ или ОБЪЕДИНИТЬ ВСЕ + СГРУППИРОВАТЬ ПО?

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

В практике разработки на платформе 1С перед программистом часто встает задача сведения данных из нескольких источников. Типичный пример: необходимо получить таблицу, содержащую одновременно данные о количестве (из одной таблицы) и о сумме (из другой) в разрезе номенклатуры. Существует два основных архитектурных подхода к решению этой задачи: использование различных типов соединений (ЛЕВОЕ, ПОЛНОЕ) или использование конструкции ОБЪЕДИНИТЬ ВСЕ с последующей группировкой. Разберем подробно плюсы и минусы каждого метода, проанализируем их влияние на производительность и выясним, какой вариант считается «золотым стандартом».

Метод 1: Использование ЛЕВОГО СОЕДИНЕНИЯ

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

Рассмотрим пример кода:


ВЫБРАТЬ
    ТабКоличество.Номенклатура КАК Номенклатура,
    ТабКоличество.Количество КАК Количество,
    ЕСТЬNULL(ТабСумма.Сумма, 0) КАК Сумма
ИЗ
    ТаблицаКоличество КАК ТабКоличество
        ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаСумма КАК ТабСумма
        ПО ТабКоличество.Номенклатура = ТабСумма.Номенклатура

Особенности и риски:

Метод 2: ОБЪЕДИНИТЬ ВСЕ + СГРУППИРОВАТЬ ПО

Этот подход заключается в том, что мы сначала собираем все данные в один «плоский» список, а затем «схлопываем» их по ключевым полям с помощью агрегатных функций (СУММА, МАКСИМУМ и т.д.).

Проанализируем пример реализации:


ВЫБРАТЬ
    ВложенныйЗапрос.Номенклатура КАК Номенклатура,
    СУММА(ВложенныйЗапрос.Количество) КАК Количество,
    СУММА(ВложенныйЗапрос.Сумма) КАК Сумма
ИЗ
    (ВЫБРАТЬ
        ТабКоличество.Номенклатура КАК Номенклатура,
        ТабКоличество.Количество КАК Количество,
        0 КАК Сумма
    ИЗ
        ТаблицаКоличество КАК ТабКоличество
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        ТабСумма.Номенклатура,
        0,
        ТабСумма.Сумма
    ИЗ
        ТаблицаСумма КАК ТабСумма) КАК ВложенныйЗапрос

СГРУППИРОВАТЬ ПО
    ВложенныйЗапрос.Номенклатура

Преимущества метода:

  1. Надежность: Данные никогда не теряются. Если номенклатура есть хотя бы в одном источнике, она попадет в итоговую выборку.
  2. Отсутствие дублей: Метод исключает арифметические ошибки, связанные с «размножением» строк при связях «один ко многим». Каждая цифра попадает в общую кучу ровно один раз.
  3. Масштабируемость: Если завтра нам понадобится добавить третий показатель (например, Вес), мы просто допишем еще один блок ОБЪЕДИНИТЬ ВСЕ. В случае с соединениями нам пришлось бы пересматривать всю цепочку связей и логику ЕСТЬNULL.

Технический анализ производительности

Разберем ситуацию с точки зрения СУБД (SQL Server или PostgreSQL). Существует мнение, что соединения работают быстрее за счет индексов, однако это не всегда так.

Работа с составными типами: В 1С поля типа ЛюбаяСсылка на уровне базы данных состоят из нескольких колонок (тип и идентификатор). При использовании СОЕДИНЕНИЯ СУБД вынуждена сравнивать все эти колонки для каждой пары строк. В случае с ОБЪЕДИНЕНИЕМ и последующей группировкой нагрузка на сервер часто оказывается более предсказуемой, так как используется алгоритм Hash Aggregate.

Планы запросов:

Когда и что выбирать? Рекомендации

Выясним причину, по которой опытные разработчики и эксперты 1С отдают предпочтение тому или иному методу:

Выбирайте ЛЕВОЕ СОЕДИНЕНИЕ, если:

Выбирайте ОБЪЕДИНИТЬ ВСЕ + СГРУППИРОВАТЬ ПО, если:

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

← На главную