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

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

Зачастую перед разработчиками 1С встает задача получить аналитические данные из регистров накопления за разные периоды (например, для сравнения лимитов и фактических расходов по месяцам). Многие начинают решать эту проблему, обходя данные в цикле, что существенно замедляет работу системы при больших объемах информации. Рассмотрим, как эффективно решить эту задачу средствами самого языка запросов 1С.

Принцип группировки по периодам

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

Рассмотрим по шагам, как выстроить такой запрос:

  1. Обращаемся к виртуальной таблице Обороты регистра накопления.
  2. В поле Период применяем функцию НАЧАЛОПЕРИОДА(Регистр.Период, МЕСЯЦ). Это позволит «схлопнуть» все движения внутри месяца в одну запись.
  3. Группируем результат по контрагенту и полученному периоду.
  4. Суммируем показатель СуммаОборот.

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

Реализация логики через объединение данных

Если вам необходимо в одной выборке совместить данные из регистра Лимиты и данные о фактических Расходах, мы рекомендуем использовать левое соединение. Давайте проанализируем, как это выглядит программно:


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

Почему стоит избегать циклов

Когда вы пишете запрос внутри цикла Для Каждого, каждый проход цикла отправляет отдельный запрос к серверу базы данных. Это создает колоссальную нагрузку на сеть и сервер, а также приводит к блокировкам. Используя предложенный выше метод, вы отправляете один единственный запрос, всю тяжелую работу по которому берет на себя SQL-сервер. Он оптимизирован для таких операций и справится с задачей в разы быстрее.

Советы по оптимизации запросов

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

Попробуйте внедрить данные методы в ваш код. Вы заметите, что структура запроса становится прозрачнее, а время выполнения отчета существенно сокращается. Работа с НАЧАЛОПЕРИОДА — это стандарт де-факто при построении любой аналитики в 1С.

← На главную