Как с помощью запроса или алгоритма найти строки в 1С, сумма которых равна заданному числу?

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

Задача поиска набора записей в регистре или таблице, сумма которых в точности соответствует целевому значению, является классической задачей компьютерных наук, известной как «Задача о сумме подмножества». В рамках разработки на платформе 1С мы часто сталкиваемся с необходимостью сверки оплат с накладными или поиска комбинаций проводок. Давайте разберем, как подходить к решению этой задачи, учитывая возможности 1С и ограничения SQL-запросов.

Решение для частного случая: поиск двух строк через запрос

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

  1. Выгружаем данные из регистра во временную таблицу.
  2. Соединяем временную таблицу с её копией (без условия соединения или с условием, чтобы избежать дублирования пар).
  3. Применяем фильтр по сумме.

Посмотрим, как это выглядит в коде запроса:


ВЫБРАТЬ
    Т1.Сумма КАК Сумма1,
    Т2.Сумма КАК Сумма2,
    Т1.Сумма + Т2.Сумма КАК Итого
ПОМЕСТИТЬ ВТ_Данные
ИЗ РегистрНакопления.ВашРегистр КАК Т1
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ВашРегистр КАК Т2
    ПО Т1.Период = Т2.Период // Ограничение, если нужно
ГДЕ
    Т1.Сумма + Т2.Сумма = &ИскомаяСумма
    И Т1.Ссылка <> Т2.Ссылка;

Важно: Данный метод создает декартово произведение. Если в таблице 1000 записей, запрос может обработать до миллиона комбинаций, что критически скажется на производительности. Применяйте этот метод только для небольших выборок.

Ограничения использования SQL-запросов

Необходимо осознавать, что запросы в 1С (и SQL в целом) плохо приспособлены для перебора всех возможных комбинаций. Если количество слагаемых заранее неизвестно (например, сумма может складываться из 3, 5 или 10 строк), построить универсальный запрос практически невозможно. Попытка создать множество соединений таблицы самой с собой приведет к экспоненциальному росту нагрузки и, вероятнее всего, к ошибке нехватки памяти на сервере.

Программная реализация: метод перебора (Backtracking)

Для решения задачи, где количество слагаемых не ограничено двумя строками, мы рекомендуем использовать алгоритм «с возвратом» (Backtracking) на встроенном языке 1С. Этот метод позволяет эффективно управлять процессом поиска.

Рассмотрим логику работы алгоритма:

  1. Выгружаем данные регистра в Массив или ТаблицаЗначений.
  2. Сортируем данные для оптимизации поиска (например, по убыванию суммы).
  3. Рекурсивно вызываем функцию, которая пытается добавить текущее число к накопленной сумме.
  4. Если сумма совпадает с целевой — сохраняем результат.
  5. Если сумма превышает целевую — прерываем текущую ветку рекурсии (откат).

Проанализируем пример логики функции:


Процедура НайтиКомбинацию(СписокЧисел, ЦелеваяСумма, ТекущийИндекс, ТекущаяСумма, ТекущийПуть)
    Если ТекущаяСумма = ЦелеваяСумма Тогда
        // Решение найдено, обрабатываем результат
        Возврат;
    КонецЕсли;

    Для Индекс = ТекущийИндекс По СписокЧисел.Количество() - 1 Цикл
        Число = СписокЧисел[Индекс];
        Если ТекущаяСумма + Число <= ЦелеваяСумма Тогда
            ТекущийПуть.Добавить(Число);
            НайтиКомбинацию(СписокЧисел, ЦелеваяСумма, Индекс + 1, ТекущаяСумма + Число, ТекущийПуть);
            ТекущийПуть.Удалить(ТекущийПуть.Количество() - 1); // Откат
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Практические советы по оптимизации поиска

Чтобы алгоритм работал быстро, воспользуемся следующими рекомендациями:

В завершение подчеркнем: универсального «волшебного» запроса для этой задачи не существует. Наиболее надежный путь — это подготовка данных запросом и последующая обработка этой выборки алгоритмом на встроенном языке 1С. Такой подход обеспечит стабильность работы вашей системы и предсказуемую производительность.

← На главную