Почему запрос ОБЪЕДИНИТЬ не группирует записи по одному полю и как получить суммированный результат

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

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

Различие механизмов ОБЪЕДИНИТЬ и ОБЪЕДИНИТЬ ВСЕ

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

Важно понимать: оператор ОБЪЕДИНИТЬ работает по принципу исключения дублей целых строк. Это аналог конструкции ВЫБРАТЬ РАЗЛИЧНЫЕ, примененной к итоговому результату объединения. Если в строках отличается хотя бы один символ или одно значение в любой из колонок, такие строки считаются разными и не объединяются.

Рассмотрим подробнее два варианта использования этого оператора:

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

Почему не происходит автоматическая группировка

Выясним причину, по которой ожидания автора не совпали с реальностью. Когда мы пишем:


ВЫБРАТЬ "Чел1" КАК Поле1, 12 КАК Поле2, NULL КАК Поле3
ОБЪЕДИНИТЬ
ВЫБРАТЬ "Чел1", NULL, 100

Для системы это две принципиально разные записи:

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

Пошаговое решение задачи: объединение с последующей группировкой

Чтобы получить результат, где по полю "Чел1" будет выведена одна строка со значениями 12 и 100 одновременно, нам нужно выполнить объединение во вложенном запросе (или временной таблице), а затем применить группировку во внешнем запросе. Разберем этот алгоритм по шагам.

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

Шаг 2. Оборачиваем во вложенный запрос. Даем нашей объединенной таблице псевдоним (например, ВложеннаяВыборка).

Шаг 3. Применяем агрегатные функции. К числовым полям применяем СУММА(), а к строковым или ссылочным, если нужно выбрать «хотя бы какое-то» заполненное значение, — МАКСИМУМ().

Проанализируем итоговый код решения:


ВЫБРАТЬ
    ВложеннаяВыборка.Поле1 КАК Поле1,
    СУММА(ВложеннаяВыборка.Поле2) КАК Поле2,
    СУММА(ВложеннаяВыборка.Поле3) КАК Поле3
ИЗ
    (ВЫБРАТЬ
        "Чел1" КАК Поле1,
        12 КАК Поле2,
        NULL КАК Поле3
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
        "Чел1",
        NULL,
        100) КАК ВложеннаяВыборка

СГРУППИРОВАТЬ ПО
    ВложеннаяВыборка.Поле1

В данном примере функция СУММА() корректно обработает NULL. В языке запросов 1С (и в большинстве диалектов SQL) агрегатные функции игнорируют значения NULL. Таким образом, СУММА(12, NULL) даст результат 12, а СУММА(NULL, 100) даст 100.

Технические нюансы и рекомендации

Рассмотрим несколько важных моментов, которые помогут избежать ошибок при использовании подобных конструкций:

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

← На главную