Зачастую перед разработчиками 1С встает задача получить аналитические данные из регистров накопления за разные периоды (например, для сравнения лимитов и фактических расходов по месяцам). Многие начинают решать эту проблему, обходя данные в цикле, что существенно замедляет работу системы при больших объемах информации. Рассмотрим, как эффективно решить эту задачу средствами самого языка запросов 1С.
Самый правильный и производительный способ решения — использование встроенных функций языка запросов для приведения дат к общему знаменателю. Вместо того чтобы выполнять отдельные запросы для каждого месяца или года, мы используем функцию НАЧАЛОПЕРИОДА.
Рассмотрим по шагам, как выстроить такой запрос:
Обороты регистра накопления.Период применяем функцию НАЧАЛОПЕРИОДА(Регистр.Период, МЕСЯЦ). Это позволит «схлопнуть» все движения внутри месяца в одну запись.СуммаОборот.При таком подходе сервер базы данных вернет готовую таблицу, где каждая строка будет содержать сумму расходов конкретного контрагента за конкретный месяц. Это позволяет избежать лишних обращений к СУБД.
Если вам необходимо в одной выборке совместить данные из регистра Лимиты и данные о фактических Расходах, мы рекомендуем использовать левое соединение. Давайте проанализируем, как это выглядит программно:
ВЫБРАТЬ
Лимиты.Контрагент КАК Контрагент,
Лимиты.СуммаЛимита КАК Лимит,
ЕСТЬNULL(Расходы.СуммаОборот, 0) КАК ФактРасхода
ИЗ
РегистрНакопления.Лимиты.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Лимиты
ЛЕВОЕ СОЕДИНЕНИЕ
(ВЫБРАТЬ
РасходыОбороты.Контрагент КАК Контрагент,
НАЧАЛОПЕРИОДА(РасходыОбороты.Период, МЕСЯЦ) КАК Месяц,
СУММА(РасходыОбороты.СуммаОборот) КАК СуммаОборот
ИЗ
РегистрНакопления.Расходы.Обороты(&НачалоПериода, &КонецПериода, Регистратор, ) КАК РасходыОбороты
СГРУППИРОВАТЬ ПО
РасходыОбороты.Контрагент,
НАЧАЛОПЕРИОДА(РасходыОбороты.Период, МЕСЯЦ)) КАК Расходы
ПО
Лимиты.Контрагент = Расходы.Контрагент
Когда вы пишете запрос внутри цикла Для Каждого, каждый проход цикла отправляет отдельный запрос к серверу базы данных. Это создает колоссальную нагрузку на сеть и сервер, а также приводит к блокировкам. Используя предложенный выше метод, вы отправляете один единственный запрос, всю тяжелую работу по которому берет на себя SQL-сервер. Он оптимизирован для таких операций и справится с задачей в разы быстрее.
Чтобы ваш отчет или обработка работали максимально быстро, придерживайтесь следующих правил:
&НачалоПериода и &КонецПериода в виртуальных таблицах. Это снижает количество обрабатываемых записей на этапе чтения из БД.ЕСТЬNULL при соединении таблиц, чтобы избежать появления пустых значений NULL, которые могут привести к ошибкам при арифметических операциях.ВЫБОР КОГДА внутри функции СУММА. Это позволяет получить итоговые суммы в разных колонках одной строки.Попробуйте внедрить данные методы в ваш код. Вы заметите, что структура запроса становится прозрачнее, а время выполнения отчета существенно сокращается. Работа с НАЧАЛОПЕРИОДА — это стандарт де-факто при построении любой аналитики в 1С.