Как в 1С объединить данные по продажам за разные годы и текущие остатки в одном отчете?

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

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

Анализируем проблему неверных соединений

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

  1. Потеря данных: При использовании левого соединения со справочником Склады (как основным), если продажи осуществлялись по складу, которого нет в выборке (или наоборот), данные могут «уплыть» в пустые строки.
  2. Дублирование остатков: Если соединение выполнено некорректно (например, только по номенклатуре без учета склада), остаток товара может просуммироваться и отобразиться напротив каждой строки продажи, что даст неверную итоговую сумму.
  3. Сложные условия связи: Использование ИЛИ в условиях соединения (например, ПО ВТ1.Склад = ВТ4.Склад ИЛИ ВТ2.Склад = ВТ4.Склад) крайне негативно сказывается на производительности и часто выдает непредсказуемый результат в виде декартова произведения строк.

Чтобы избежать этих проблем, проанализируем более надежный механизм — объединение таблиц.

Решение задачи через «ОБЪЕДИНИТЬ ВСЕ»

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

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


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

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

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

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

ВЫБРАТЬ
    ТоварыНаСкладахОстатки.Номенклатура,
    ТоварыНаСкладахОстатки.Склад,
    0,
    0,
    ТоварыНаСкладахОстатки.КоличествоОстаток
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОстатков, ) КАК ТоварыНаСкладахОстатки

В данном примере мы собрали три разных потока данных в одну временную таблицу ВТ_Данные. Каждая запись несет информацию либо только о продажах одного года, либо только о продажах другого, либо только об остатках. При этом колонки «чужих» ресурсов заполнены нулями.

Итоговая группировка данных

Теперь нам необходимо «схлопнуть» эти записи, чтобы для каждой пары Номенклатура + Склад была только одна итоговая строка. Рассмотрим подробнее финальный запрос:


ВЫБРАТЬ
    Т.Номенклатура КАК Номенклатура,
    Т.Склад КАК Склад,
    СУММА(Т.ПродажиПрошлыйГод) КАК ПродажиПрошлыйГод,
    СУММА(Т.ПродажиПозапрошлыйГод) КАК ПродажиПозапрошлыйГод,
    СУММА(Т.Остаток) КАК Остаток
ИЗ
    ВТ_Данные КАК Т
ГДЕ
    (Т.ПродажиПрошлыйГод <> 0 ИЛИ Т.ПродажиПозапрошлыйГод <> 0)
СГРУППИРОВАТЬ ПО
    Т.Номенклатура,
    Т.Склад

Разберем ситуацию с фильтрацией. В условии ГДЕ мы указали, что нам нужны только те позиции, по которым были продажи. Если по товару есть остаток, но не было продаж за оба года, он не попадет в отчет. Если же задача стоит иначе — выводить все товары, по которым есть остатки, независимо от продаж — это условие нужно удалить.

Важные рекомендации по оптимизации

При работе с виртуальными таблицами 1С важно помнить о производительности. Проанализируем несколько критических моментов:

  1. Параметры виртуальных таблиц: Всегда передавайте фильтры (например, по списку номенклатуры или конкретным складам) в параметры виртуальной таблицы (в скобках после имени регистра). Это работает быстрее, чем фильтрация в секции ГДЕ.
  2. Обращение через точку в запросе: Старайтесь избегать конструкций вида Продажи.ДокументПродажи.Склад. Каждая такая «точка» — это неявное левое соединение со всеми таблицами документов-регистраторов, что может катастрофически замедлить отчет. Если в регистре Продажи нет измерения Склад, используйте регистры, где склад является аналитикой в явном виде.
  3. Использование Системы Компоновки Данных (СКД): Если вы разрабатываете отчет на СКД, можно пойти еще более простым путем. Создайте три отдельных набора данных — два запроса к оборотам продаж и один к остаткам. На закладке «Связи наборов данных» свяжите их по полям Номенклатура и Склад. В этом случае СКД сама выполнит аналог FULL OUTER JOIN, корректно распределив данные по колонкам и строкам.

Как вывести иерархию (Номенклатура — Склад)

Для того чтобы отчет выглядел структурно (сначала идет название товара, а ниже — список складов, на которых он есть или продавался), мы рекомендуем использовать механизм группировок. В итоговом запросе или в настройках СКД укажите иерархическую структуру:

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

Подводя итог, можно сказать, что ключ к созданию верного отчета по остаткам и продажам — это отказ от сложных соединений в пользу вертикального объединения данных с последующей горизонтальной группировкой ресурсов. Этот метод гарантирует точность данных и высокую скорость работы программы.

← На главную