Почему в итоговом запросе 1С затраиваются данные и как это исправить

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

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

Анализ причины: почему данные «затраиваются»?

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

В исходном запросе автора сообщения мы видим три блока объединения. В каждом блоке выбирается поле ВТ_ТчТовары.Количество. Если в документе было 20 единиц товара, то после трех объединений (по трем организациям) в результирующей таблице окажется три строки с этим же товаром, и в каждой будет стоять число 20. Когда в финальном запросе применяется функция СУММА(Количество), платформа честно складывает 20 + 20 + 20 и выдает 60. Происходит арифметическое размножение данных, которое не соответствует реальности.

Вариант решения №1: Исправление группировок

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

Рассмотрим пример исправленного кода:


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

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

Вариант решения №2: Использование конструкции ВЫБОР

Разобранный выше метод с объединениями является «тяжелым» для системы, так как заставляет СУБД выполнять несколько похожих запросов и склеивать их. Более профессиональный и производительный подход — использование условного суммирования через конструкцию ВЫБОР. Проанализируем, как это сделать за один проход.

Вместо трех объединений мы можем получить все остатки по нужным организациям одним пакетом и разложить их по колонкам:


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

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

Архитектурные рекомендации и масштабируемость

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

Для решения этой задачи в 1С существуют два основных пути:

  1. Система компоновки данных (СКД): Это эталонный способ. В СКД вы просто выбираете Организация как обычное поле. В настройках отчета вы создаете таблицу, где Номенклатура находится в строках, а Организация — в колонках. Платформа сама динамически развернет столько столбцов, сколько организаций будет найдено в базе.
  2. Программное построение запроса: Если вы все же используете программный вывод, текст запроса должен собираться в цикле. Мы обходим массив организаций и динамически добавляем в строку запроса фрагменты с оператором ВЫБОР.

Типичные ловушки при соединениях с регистрами

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

В типовых конфигурациях (таких как УТ 11, ERP, КА 2) остатки хранятся в разрезе ключей аналитики номенклатуры. Если по одной номенклатуре в регистре есть остатки на разных складах или с разными характеристиками (а в условии соединения вы их не указали), то на одну строку из таблицы товаров документ подберет несколько строк из остатков. Результат — сумма снова будет завышена.

Рекомендация: Перед соединением с основной таблицей всегда делайте предварительную выборку остатков во временную таблицу, где данные уже сгруппированы строго до уровня Номенклатура + Организация. Это гарантирует связь «один к одному» и исключит любые дубли.

Итоги

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

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

← На главную