Нарастающие итоги в запросе и методы ускорения его выполнения.
Любезные критики, смотрите P.S. к статье.
Есть множество задач, в которых требуется получение и/или обработка нарастающих итогов. В частности это дебиторская/кредиторская задолженность и расчетные листки. Задача легко решается в рамках встроенного языка, но по разным причинам это не всегда приемлемо (подробнее см. P.S.). Язык запросов 1с позволяет получить нарастающие итоги. Как подсказывает логика, итоги должны нарастать относительно какого-либо показателя. Самый распространенный случай – период. Именно такой случай и будет рассматривать. Так как лично столкнулся с необходимостью использования нарастающих итогов в рамках анализа дебиторской задолженности, то и в статье будем рассматривать её.
Итак, для чего при анализе дебиторской задолженности могут потребоваться нарастающие итоги? Для формирования списка документов по текущей задолженности (при этом абсолютно не важно с какой степенью детализации ведутся взаиморасчеты – алгоритм такой же). Этот список даёт важную информацию для дальнейшего анализа – дата возникновения задолженности, число дней долга, если есть параметр числа дней задолженности, то количество дней просрочки, сумма просроченного долга, ну и сам список документов долга.
Для начала нам потребуется получить список документов взаиморасчетов контрагента:
Реализация товаров и услуг №1 500р
Реализация товаров и услуг №2 1000р
Платежное поручение исходящее №1 -500р
Реализация товаров и услуг №3 1200р
Итого 2200р
Для того чтобы получить нарастающий итог нужно использовать ещё одну такую же таблицу и связать её с первой. Связывать нужно по дате (при совпадении времени можно дополнительно сравнивать по моменту времени), но связывать не через равенство, а через сравнение >= или
Реализация товаров и услуг №1 500р 500р
Реализация товаров и услуг №1 500р 1000р
Реализация товаров и услуг №1 500р -500р
Реализация товаров и услуг №1 500р 1200р
Реализация товаров и услуг №2 1000р 1000р
Реализация товаров и услуг №2 1000р -500р
Реализация товаров и услуг №2 1000р 1200р
Платежное поручение исходящее №1 -500р -500р
Платежное поручение исходящее №1 -500р 1200р
Реализация товаров и услуг №3 1200р 1200р
Как-то некрасиво…А, ну да! Нужно сгруппировать по всем поля Основного списка с суммированием поля вспомогательного. В итоге получим искомое:
Реализация товаров и услуг №1 500р 2200р
Реализация товаров и услуг №2 1000р 1700р
Платежное поручение исходящее №1 -500р 700р
Реализация товаров и услуг №3 1200р 1200р
Пример запроса
ВЫБРАТЬ
ПериодыИзменения.Период КАК Время,
СУММА(Регистр.СуммаОборот) КАК Сумма
ИЗ
(ВЫБРАТЬ РАЗЛИЧНЫЕ
ПродажиПоДисконтнымКартам.Период КАК Период
ИЗ
РегистрНакопления.ПродажиПоДисконтнымКартам КАК ПродажиПоДисконтнымКартам
ГДЕ
ПродажиПоДисконтнымКартам.ДисконтнаяКарта = &Ссылка) КАК ПериодыИзменения
ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
ПродажиПоДисконтнымКартамОбороты.Период КАК Период,
ПродажиПоДисконтнымКартамОбороты.СуммаОборот КАК СуммаОборот
ИЗ
РегистрНакопления.ПродажиПоДисконтнымКартам.Обороты(, , Регистратор, ДисконтнаяКарта = &Ссылка) КАК ПродажиПоДисконтнымКартамОбороты
ГДЕ
ПродажиПоДисконтнымКартамОбороты.ДисконтнаяКарта = &Ссылка) КАК Регистр
ПО ПериодыИзменения.Период >= Регистр.Период
СГРУППИРОВАТЬ ПО
ПериодыИзменения.Период
Все…..можно было бы и так сказать, но у такого решения есть один существенный недостаток – с ростом числа строк в таблице время выполнения запроса увеличивается геометрически (или экспоненциально). Для ускорения требуется оптимизация. Приведу 3 способа:
1. Ограничить период в запросе. Самый распространенный (честно говоря единственный найденный мной на степях интернета), позволяет ограничить число строк в таблице, а значит и ускорить время запроса. Наиболее легкий способ, но имеет недостаток – всё что не входит в период не суммируется – можно и не угадать с периодом, да и необходимее периоды иногда бывают очень большими.
2. Метод последовательного приближения. Строго говоря, метод не ускоряет получения нарастающих итогов для всей таблицы, а только ускоряет поиск нужного значения с использованием нарастающих итогов. Вернемся к примеру с дебиторской задолженностью. Таблица документов долга не будет совпадать со всей таблицей – 500 рублей уже заплатили. Нам требуется получить таблицу с документами возникновения долга (реализация) сумма которых в обратном порядке от последнего числа равна текущему долгу 2200р. Для таких малых таблиц ускорение не требуется, но когда речь идет о большом количестве контрагентов и взаиморасчетах за несколько лет, то можно применить метод последовательного приближения. Идея заключается в том, чтобы сгруппировать документы по периоду и детализировать только нужные периоды. Удобнее всего это делать через пакетные запросы. В моем случае я использовал следующий алгоритм: сначала получил 3 дополнительные таблицы: группировка по годам, группировка по месяцам и группировка по дням. Сначала уже известным способом для таблицы по годам рассчитываем нарастающие итоги. Далее получаем из неё 2 таблицы: если сумма долга с нарастанием для года меньше общего долга, то включаем его в таблицу безусловного включения в конечную таблицу, а первый год, где итоговая сумма больше долга (год с минимальным превышением), отправляем в таблицу для дальнейшего рассмотрения и не забываем передать туда сумму остатка долга (общая сумма долга минус сумма долга из таблицы безусловного включения). Именно по этой таблице отбираем данные из таблицы сгруппированной по месяцам. И также как для таблицы с годами, делим её на 2 таблицы по сумме остаточного долга. Далее таблицу для дальнейшего рассмотрения используем для отбора в таблице по дням. Ну и после делаем всё тоже самое для дальнейшего рассмотрения по дням и основной таблицы.. В результате мы получаем следующие таблицы: безусловное включение по годам, безусловное включение по месяцам, безусловное включение по дням и документы долга в первый день (наиболее удаленные от дня отчета) долга. В последней фазе отбираем из основной таблицы конкретные документы с использованием вышеперечисленных таблиц. Объединяем и вуаля! Готовая таблица документов долга.
Недостаток этого метода – сложность реализации. Сама реализация на //infostart.ru/public/20221/ - ссылка на файл "Новый запрос"
3. Метод сложения периодов. Более универсальный метод и позволяет ускорить именно получение нарастающих итогов. При расчете нарастающих итогов в условие связи добавляется дополнительное условие, чтобы разделить общую таблицу на подтаблицы (желательно помельче). Далее последовательно объединяем эти подтаблицы в более крупные подтаблицы с нарастанием итогов - к каждому последующему периоду прибавляется итоги (последняя сумма в подтаблице) предыдущих периодов. И так далее в зависимости от выбранного для конкретного случая числа итераций.
Недостаток метода – тоже достаточная сложность реализации и то, что этот метод не разработан в деталях – я окончательно его сформулировал только что.
P.S. «Не надо ругать пианиста, он играет как умеет». Я работаю с 8кой, поэтому не могу сказать, что частности реализации методов для 7ки будет таким же (если это вообще возможно), но общие алгоритмы универсальны.
По поводу необходимости получать нарастающие итоги в запросе - в 1с 8 есть возможность создание отчетов с помощью мастеров только из запроса, не используя встроенный язык. Это существенно ускоряет создание отчетов. И когда отчет сам по себе очень прост, то переходить из-за нарасающих итогов на встроенный язык нецелесообразно. Второй случай, когда структура выводимых данных иерархична и строится в нескольких разрезах - язык запросов более гибок. Пример в статье дан именно как пример, для лучшего понимания алгоритма - в реальной задаче такой частный случай с одним клиентом и одним показателем легче решить встроенным языком. Кроме того, как я уже говорил в статье, у запросного метода есть один глобальный недостаток - рост времени выполнения при увеличении объема исходных данных. Но недостаток это можно устранить сложными методами оптимизации, после которых запрос выполняется быстрее встроенного языка.
Метод подсчета нарастающих итогов известен и много раз публиковался на форумах, но именно подробной статьи не было. Метод простой, и статья только про него вышла бы очень короткой. Поэтому добавил описание методов ускорения расчетов. 1 метод используют для ускорения расчетов только запросом (если ускорение вообще используется) все отчеты по задолженности, которые я рассматривал. И в некоторых комментариях я уже писал, что ограничение глубины рассмотрения задолженности – это метод Александра Македонского для узлов – проблема вроде бы решена, только веревка уже не целая. 2 метод я использую для своих отчетов по дебиторской задолженности. После применения этого метода время исполнения отчета для достаточно крупной базы (по всем покупателям) уменьшилось с более 30 минут, до минуты и менее – и не надо про производительность и т.д. всё это уже проверялось. Все варианты отчетов можно посмотреть в моих разработках, в т.ч. и запрос по методу 2 в чистом виде. Ну и 3 метод мне пока не требовался и окончательно я его сформулировал только сейчас. Дискуссия и плюсование поощряется.
Вступайте в нашу телеграмм-группу Инфостарт
Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.
См. также
Инструментарий разработчика Роли и права Запросы СКД Разработчик Руководитель проекта 1С:Предприятие 8 Платные (руб)
Инструменты для разработчиков 1С 8.3 и 8.5: Infostart Toolkit. Автоматизация и ускорение разработки на управляемых формах. Легкость работы с 1С.
16500 руб.
02.09.2020 285573 1606 423
Инструментарий разработчика Запросы Разработчик 1С 8.3 1С:Бухгалтерия 3.0 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)
Структура запроса. Обработка визуально показывает, из какого количества подзапросов состоит запрос.
2 стартмани
06.07.2026 4945 65 XSlava 20
Запросы Разработчик 1С 8.3 Россия Бесплатно (free)
Визуальный «Конструктор запроса» 1С, встроенный прямо в VS Code, — аналог конструктора из Конфигуратора и EDT, но без запуска платформы. Расширение читает конфигурацию, выгруженную в файлы, позволяет собрать запрос мышью и генерирует корректный текст на языке запросов 1С (SDBL). Открывает уже существующий текст запроса из кода для правки и — что особенно ценно — сохраняет комментарии при цикле «открыть - править - сохранить». Подходит тем, кто пишет код 1С в VS Code, держит под рукой множество проектов и не хочет ради одного запроса запускать тяжёлый Конфигуратор или EDT.
26.06.2026 10660 Alex_YAM 7
Нейросети Инструментарий разработчика Запросы Разработчик 1С:Предприятие 8 Абонемент ($m)
Консоль запросов 1.0: добавлен ИИ-помощник (запрос в DeepSeek), который помогает быстрее получать каркас Запроса 1С Сформулируйте простое описание; нажмите кнопку – получите результат прямо в консоли. Где дальше его можно дорабатывать и тестировать. 28.5.2026 Добавил "Консоль запросов 2.0" (запрос в DeepSeek + Claude) 4.10.2026 Обновил "Консоль запросов 2.0"
3 стартмани
20.05.2026 9562 46 German4739 72
WEB-интеграция Запросы Разработчик 1С 8.3 Абонемент ($m)
Post1C - это внешняя обработка, которая превращает 1С в полноценный инструмент для тестирования REST API. Всё управление сосредоточено в одном окне: настройка запроса, выполнение, просмотр ответа и генерация кода - без переключения между формами. Аналог Postman, но работающий в привычной среде 1С.
1 стартмани
02.04.2026 4638 105 priem_nv 27
Запросы Механизмы типовых конфигураций Разработчик 1С:Предприятие 8 1С:Управление торговлей 11 Россия Бесплатно (free)
Предлагается обзор работы с объектной моделью запроса по схемам запросов типовым функционалом УТ 11.5.
09.10.2025 13397 aximo 18
Инструментарий разработчика Запросы Разработчик 1С:Предприятие 8 1С:Зарплата и кадры государственного учреждения 3 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)
QueryConsole1C — расширение, включающее консоль запросов с поддержкой исполняемых представлений — аналогов виртуальных таблиц, основанных на методах программного интерфейса ЗУП. Оно позволяет выполнять запросы с учётом встроенной бизнес-логики, отлаживать алгоритмы получения данных и автоматически генерировать код на встроенном языке 1С.
1 стартмани
16.05.2025 13660 168 zup_dev 32
Инструментарий разработчика Запросы Разработчик 1С:Предприятие 8 1С:ERP Управление предприятием 2 Абонемент ($m)
В данной публикации рассказывается о решении, которое позволяет находить сразу все ошибки в тексте запроса за раз, а не только самую первую.
2 стартмани
05.03.2025 7714 25 XilDen 12
"Видала я котов без улыбок, но вот улыбку без кота ещё ни разу" (с) Алиса
Теперь по-русски.
Я видал много программ без описаний, но вот описание без программы встретишь не часть.
.. просто сказали - так надо ... просто кто-там и ему тАк удобно - вот теперь все на него и равняются ...
... (11) ... так КАК же данную задачу надо решать ...? товарищь hogik..?
... вотРасскажите ...
" так КАК же данную задачу надо решать ...? товарищь hogik..?"
Уважаемый Александр ("Шёпот теней"), я Вам не товарищ. А если это "партийное" обращение, то тем более не к месту. Т.к. будучи рожденным в 1955 году, я даже в комсомоле не состоял... ;-)
А решение описано в предыдущем (15) сообщении данной темы.
Вопрос регулярно подымается на различных форумах. Иногда очень неудобно увеличивать срок разработки отчета из-за необходимости писать код для программной обработки данных и их вывода.
Кроме того, методы последовательного приближения вполне применим и для программного исполнения.
"применение алгоритмов из статьи существенно ускорило"
Возможно и ускорило по сравнению с алгоритмом от которого начинаются Ваши рассуждения. Только, думаю, еще больше будет ускорение, если (упрощенно говоря(!) - на Вашем примере) "взять список документов взаиморасчетов контрагента" и просмотреть его в обычном цикле из трех операторов с подсчетом нарастающего итога. При этом "взять список документов" можно и запросом, а можно и внутри этого же цикла получать поштучно.
"3 оператора, подойдут только если нам нужен итог"
"Пример в статье для самого простого случая."
Ну и мой пример для этого самого случая. ;-)
"говорю, что есть задачи, где он менее эффективен и удобен, чем запросный метод."
Именно - так. Но мы то говорим о конкретной задаче, где запросный метод НЕ эффективен и НЕ удобен. И Ваша статья, на мой взгляд, это подтверждает.
Спасибо за интересную беседу. Желаю успехов.
... есть язык программирования процедурный а есть декларативный ...
... зачем бегать по документам - когда результаты хранятся не там где хранятся данные ... есть сервер (как хранилище) и есть пльзователь (как клиент) ... запрос - работает тАмА а процедура Тута ...
... есть "правильно" с т.з. производительности и общей политики а есть "правильно" с т.з. простоты и быстроты ...
... гармония в середине ...
... никогДА не думал что товарищЬ это оскорбление - господин hogik ...
... вОт ...
... цель не определяет средство - но средство определяет решение ...
найдя связь между целью и решением исключим мучения относительно выбора средства ...
... )))
... вОООттАААкойФенШуй ...
Согласен, что данные методы очень удобны для использования в универсальных отчетах типа СКД, т.к. исключается программная обработка данных и позволяет уменьшить время разработки, а удобство увеличить.
Сам использую их таким образом.
Кстати в моем отчете используется вариант автоматического ограничения периода без потери "точности" (можно принудительно ограничить период с потерей части детализации если производительность не достаточна).
Я извиняюсь , но всё читал мельком, кроме текста запроса.
Да простит меня автор , но всё же лучше придерживаться рекомендаций 1с , и оформлять пакетные запросы , используя временные таблицы.
На эту тему на ИС ,кажется , сказано уже немало.
Смутило также , упоминание в комментариях "загрузки сервера" без уточнения :"приложений" или "БД".
Думаю, метод оптимизации зависит от реализации "трехзвенки" .
Возможна ситуация , когда выгоднее загрузить выделенный сервер БД запросом , чем писать оптимизационный код , используемый в сервере приложений.
А про комментарии...Я не подкован теоретически. Поэтому готов почитать хороший материал с примерами про производительность выполнения кода в различных вариантах.
Запрос, выполнение кода на машине, выполнение на сервере, один запрос, множество подзапросов в цикле, множество подзапросов в цикле на сервере....
Я говорил про то , что сервер приложений и сервер баз данных могут находиться как на разных компьютерах так и на на одном.
Это обстоятельство может быть существенным при выборе варианта оптимизации.
Материалы с примерами производительнсти для разных вариантов реализации "трехзвенки"(клиент-сервер приложений-сервер баз данных) тоже бы почитал с удовольствием.
На мой взгляд, лучшим вариантом оптимизации будет следующий :
Получим из виртуальной таблицы Обороты регистра ПродажиПоДисконтнымКартам правильно отсортированную таблицу значений Тоб
со структурой Карта, Период , СуммаОборот.
Добавим в Тоб типизированную колонку СуммаНакопления.
Теперь пишем :
ТекКарта = НеОпределено;
Для каждого Строка из Тоб Цикл
Если Строка.Карта <> ТекКарта Тогда
СуммаНакопления = Строка.СуммаОборот;
ТекКарта = Строка.Карта;
Иначе
СуммаНакопления = СуммаНакопления + Строка.СуммаОборот;
КонецЕсли;
Строка.СуммаНакопления = СуммаНакопления;
КонецЦикла; ПоказатьИтоговая Тоб - получена за один проход , теперь её можно загрузить в Запрос в виде временной таблицы и продолжить дальнейшие преобразования .
Итак , если сравнивать время исполнения запроса в тексте темы и алгоритм :
1. Выгрузка из запроса и Получение Тоб
2. Приведенный код
3. Загрузка в запрос таблицы Тоб и получение временной таблицы
То выигрыш при 100 000 записей в Тоб должен составить не менее 3 раз.
Если количество записей 1 000 000 и более то выигрыш должен составить не менее 5 раз.
Т.к. в тот момент я осваивал пакетные запросы и решил всё-таки ещё подумать, как можно обойти это ограничение, чтобы можно было обойтись средствами быстрого создания отчетов 1с 8. Результатом стал алгоритм последовательного приближения.
Плюсом этого алогоритма является то, что применить его можно как средствами пакетных запросов, так и простым кодом.
Если сравнивать запрос с последовательным приближением и выполнения кода без хитрых оптимизаций, то запрос выигрывает.
Это не теория. Я сравнивал по производительности отчеты по дебиторке и свои (разные варианты), и чужие. Пока быстрее всего - оптимизированный запрос.
Вопрос остается в другом - стоит ли отчет такой мудренной оптимизации. Для дебиторки - стоит. С получаса я сократил время до 10-20 сек и теперь могу сравнивать в одном отчете разные периоды достаточно быстро. Со старым отчетом мне даже в голову бы не пришло получить график просроченной дебиторки в разрезе дней за 3 месяца. А тут - ноу проблем.
В чем -то я согласен с Чебуром.
Статья должна быть такой . Выкинуть словесную дребедень .
Оставить : Подробный пример описания метода нарастающих итогов.
В примере выкинуть регистры - оставить только абстрактные таблицы.
Постановка задачи. (абстрактная, выкинь ты эти ПродажиПоДиск...)
Дано : таблица Т1 , структура Поле1 , Поле2 и т.д.
таблица Т2 , структура Поле1....
Нужно получить Таблицу 3 со структурой ....
В теме автора допускается вставка "таблиц". Заполнил для наглядности
Т1 и Т2 простенькими значениями и пошел текст запроса с показом изменений в демо-таблицах Т1 и Т2.
Вот так будет по-взрослому.
Словесную дребедень почищу, но только для стандартного запроса по нарастанию. Дальнейшие алгоритмы сложно описать более коротко.
Я в (32) взял твой пример с запросом , по тексту статьи следует что дело именно в нем , показал как те же данные можно получить с помощью кода. И предполагаю , что проще , быстрее, надежнее
таблицу Тоб - не получить. Заметь Тоб получена не для одной карты как у тебя в запросе , а для всех карт сразу.
Ты мне говоришь про что ?
что есть еще какой-то метод получения Тоб ?
или ты имеешь ввиду какую-то другую задачу ?
НО.... можно наложить ещё одно условие - большой объём данных. Оба варианта при этом дают неудовлетоворительные результаты по скорости. Причём запрос начинает существенно проигрывать по скорости... Для оптимизации и кода, и запроса можно применить метод последовательного приближения.
Ты утверждаешь :
1. что временную таблицу Тоб из (30) (внимание ! именно её, содержащую информацию для всех карт по периодам) ты получишь быстрее ? для большого объема информации ?
Так ?
2. Или ты утверждаешь, что целиком эту таблицу не получаешь и в твоем алгоритме она в таком виде не используется ?
Я по-прежнему тупо исхожу из текста приведенного тобой запроса
и последующих утверждений , что в получении результата этого запроса - всё дело ! Я лишь убрал условие, ограничивающее выбороку одной картой,
а сделал выходную таблицу для всех карт.
Если так , то по-моему скромному мнению , быстрее этого простого способа что-то придумать тяжело.
В статье же вроде написано всё.
Необходимость оптимизации требуется не для запроса с дисконтными картами - это всего лишь простой пример получения нарастающих итогов в запросе. Запрос по производительности сильно зависит от объема данных. Поэтому у нас получается так:
Код
+Скорость выполнения - скорость выполнения растёт линейно в зависимости от объема данных
-Скорость написания программистом отчета - если всё остальное в отчете реализуемо в рамках запроса и писать код не нужно, то для нарастающих итогов придется писать дополнительную процедуру, потом процедуру вывода отчета и т.д.
Запрос
+Скорость написания программистом отчета - весь отчет можно сделать автоматом на основе одного запроса
-Скорость выполнения запроса с нарастающими итогами - скорость растёт геометрически или экспоненциально в зависимости от объема данных
Остается только выбрать какой из вариантов более подходит под конкретную задачу.
Дальнейшая статья описывает как в более узком ряде задач можно оптимизировать алгоритм.
При анализе дебиторки не требуется вся таблица с нарастающими итогами, а только элемент таблицы, для которого нарастающие итоги превысили определенное значение. Именно это условие позволило существенно оптимизировать расчеты. Идея заключается в том, что получаем несколько таблиц сгруппированных с разной детализации (это может быть период (таблицы Год, месяц, день, запись таблицы) или число записей (деление таблиц пополам последовательно) и последовательно ищем превышение значений. Сложность алгоритма конпенсируется приростом скорости.
З.Ы. Ну уж не знаю как объяснить необходимость оптимизации, если вместо 30 минут с помощью кода получаем за 10-20 секунд с помощью оптимизированного запроса.
Напиши еще одну статью , уже без разбора альтернативных вариантов.
Только тексты запросов и объяснения к ним. Остальное - лишнее.
(40)
Это про что ? Про предложенный алгоритм в (38) ?
Любое множество данных есть не слишком большое.
Что-то более вразумительное к цитате добавить тяжело.
Если я вынесу в отдельную статью описание запроса, то это потребует тех же объяснений...Что зачем и почему, как решить по-другому...чтобы понять проблему нужно полностью её описать. Это как объяснять человеку, который не видел электричества работу атомного реактора без объяснения зачем требуется такое устройство и где его лучше применять и строить и как без него обоитись
По-прежнему считаю , что так представление метода (алгоритма) не делается. Но о вкусах не спорят.
Я привел тебе алгоритм . Скажи метод нарастающих итогов какую даст прибавку в быстродействии , по сравнению с моим запросом и обработкой ?
В конкретно твоей базе ? 5 раз, 10 раз ? сколько ?
Ты мне дай одну ссылку и имя файла которое надо скачать.
А то там много чего написано и ссылок внутри.
Метод нарастающих итогов - увеличит время выполнения.
Неоптимизированный код:оптимизированный по-моему запрос 20:1
Оптимизированный по-твоему код:оптимизированный по-моему запрос минимум 5:1
Но уменя еще вопрос . Саша , а рассматривался такой вариант :
Выбирается Период "П1" , допустим месяц . И для этого периода запускается алгоритм (38). Получили Тоб.
Из таблицы Тоб выбираются карты , для которых периода "П1" - "не хватило" и на текущий долг не набралось достаточно документов.
Для полученной временной таблицы непогашенных карт алгоритм (38) запускается еще раз с периодом "П2" , допустим "год".
И далее период "П3" - уже весь интервал для оставщихся карт с непогашенным долгом.
Не это ли есть последовательные приближения ? При таком подходе
Периоды П1,П2,П3 должны быть такими , чтобы количество записей в Тоб на каждом шаге уменьшалось в десятки , сотни раз
Речь идет о конкретной базе.О твоей. При таком подходе соотношение времен выполнения моего и твоего алгоритма должно быть
1:2.
А при удачном подборе периодов П1,П2,П3 можно жобиться 1:5.
Это прогноз , разумеется.
Ну ,как ? согласен ?
Можно прикинуть следующий вариант : запрос, выбирающий нужные движения из вирт.таблицы Обороты.
И лишь затем код , получающий Тоб
Выбрать ДисконтнаяКарта, СуммаОстаток Поместить Остатки ИЗ Регистр.ПродажиПоДисконтнымКартам.Остатки(&Дата)
//
Выбрать Об.ДисконтнаяКарта,Об.Период, Остатки.Сумма из
РегистрНакопления.ПродажиПоДисконтнымКартам.Обороты(, , Регистратор)
как Об ВнутреннееСоединение Остатки по Об.ДисконтнаКарта=Остатки.ДисконтнаяКарта
Итоги по Об.ДисконтнаяКартаИ далее понятный код получения Тоб из дерева выборки.
ВыборкаКарт = Запрос.Выполнить.Выбрать()
Пока ВыборкаКарт.Следующий() Цикл
ВыборкаДокументов = ВыборкаКарт.Выбрать();
Пока ВыборкаДокументов.Следующий() Цикл
....// создаем строку Тоб
Если //Условие// Тогда
Прервать;
КонецЕсли;
КОнецЦикла;
КОнецЦикла ; ПоказатьИтак, Саша, мы сделали очень легкий запрос к остаткам вначале, затем
сделали всего один запрос с внутренним соединением. Да база ,очень большая, но и запрос простой без суммирования вовсе - раз , условие внутреннего соединения простое - два. Особо обращаю внимание мы обратились к базе с простыми запросами на выборку всего два раза
И в конце простой обработкой с прерыванием цикла по условию создали всю таблицу Тоб.
Ей-Богу , что можно придумать быстрее и проще ? Как ?
Какие нарастающие итоги ? Какие последовательные приближения?
Зачем это всё ?
Не томи.
например, чтобы в СКД сделать некий отчет без доп.кодирования.
Данная задача должна применяться для какого-то ограниченного, не слишком большого множества данных, иначе получим проблемы с производительностью.
Только вот опять тут нельзя реализовать данный алгоритм в рамках одного запроса. А так очень неплохой алгоритм.
Я тут на тебе попробую различные варианты объяснения своего алгоритма. Какой понятнее и проще...
Мой алгоритм идет наоборот от более крупных периодов к более мелким. Но рассматриваются не документы внутри периода, а итоговые значения по периоду (т.е. сумма). Рассмотрение идет от сегодня в прошлое. Если сумма увеличения долга за год больше, чем долг, то дробим период на месяцы рассматривая опять только итоги, если меньше, то рассматриваем следующий год. Такая же фигня на уровне месяцев и так до уровня регистраторов.
В результате имеем набор таблиц
Контрагент Полных лет долга
Контрагент Полных месяцев долга
Контрагент Полных дней долга
Контрагент Документы долга в самый давний день долга
Из этих таблиц уже можно получить полный список документов долга.
1. Ты обращаешься ко всей (!) вирт.таблице Обороты с периодичностью "Регистратор" и практически всю(!) ее копируешь во временную таблицу.
ВЫБРАТЬ
ВзаиморасчетыСКонтрагентамиОбороты.Период КАК Период,
ВзаиморасчетыСКонтрагентамиОбороты.Контрагент КАК Контрагент,
ВзаиморасчетыСКонтрагентамиОбороты.Регистратор КАК Регистратор,
ВзаиморасчетыСКонтрагентамиОбороты.СуммаУпрОборот КАК СуммаУпрОборот,
ГОД(ВзаиморасчетыСКонтрагентамиОбороты.Период) КАК ГодПериод,
МЕСЯЦ(ВзаиморасчетыСКонтрагентамиОбороты.Период) КАК МесяцПериод,
ДЕНЬ(ВзаиморасчетыСКонтрагентамиОбороты.Период) КАК ДеньПериод
ПОМЕСТИТЬ Взаиморасчеты
ИЗ
РегистрНакопления.ВзаиморасчетыСКонтрагентами.Обороты(, КОНЕЦПЕРИОДА(&Дата2, ДЕНЬ), Регистратор, Контрагент В ИЕРАРХИИ (&Контрагент)) КАК ВзаиморасчетыСКонтрагентамиОбороты
ИНДЕКСИРОВАТЬ ПО
Контрагент
; Показатьтеперь эту огромную временную таблицу ты группируешь по периодам :
ВЫБРАТЬ
Взаиморасчеты.ГодПериод КАК ПериодГод,
Взаиморасчеты.МесяцПериод КАК ПериодМесяц,
Взаиморасчеты.ДеньПериод КАК ПериодДень,
Взаиморасчеты.Контрагент,
СУММА(Взаиморасчеты.СуммаУпрОборот) КАК СуммаУпрОборот
ПОМЕСТИТЬ УвеличенияДолгаДень
ИЗ
Взаиморасчеты КАК Взаиморасчеты
ГДЕ
Взаиморасчеты.СуммаУпрОборот > 0
СГРУППИРОВАТЬ ПО
Взаиморасчеты.Контрагент,
Взаиморасчеты.ГодПериод,
Взаиморасчеты.МесяцПериод,
Взаиморасчеты.ДеньПериод
; ПоказатьДважды обращаясь к огромному количесву данных- ты проиграл очень много .
В данном случае достаточно одного запроса к вирт. таблице Обороты с периодичностью Регистратор.
ВЫБРАТЬ
ВзаиморасчетыСКонтрагентамиОбороты.Контрагент КАК Контрагент,
ГОД(ВзаиморасчетыСКонтрагентамиОбороты.Период) КАК ГодПериод,
МЕСЯЦ(ВзаиморасчетыСКонтрагентамиОбороты.Период) КАК МесяцПериод,
День(ВзаиморасчетыСКонтрагентамиОбороты.Период КАК ДеньПериод
Сумма(ВзаиморасчетыСКонтрагентамиОбороты.СуммаУпрОборот) КАК СуммаУпрОборот,
ПОМЕСТИТЬ Взаиморасчеты
ИЗ
РегистрНакопления.ВзаиморасчетыСКонтрагентами.Обороты(, КОНЕЦПЕРИОДА(&Дата2, ДЕНЬ), Регистратор, Контрагент В ИЕРАРХИИ (&Контрагент)) КАК ВзаиморасчетыСКонтрагентамиОбороты
ГДЕ
ВзаиморасчетыСКонтрагентамиОбороты.СуммаУпрОборот > 0
СГРУППИРОВАТЬ ПО
Контрагент,
ГодПериод,
МесяцПериод,
ДеньПериод
ИНДЕКСИРОВАТЬ ПО
Контрагент ПоказатьМелкие замечания :
Функцию КонецПериода() применять в запросе - как-то не очень.
Индексировать - применяется в том случае если в дальнейшем
требуется многократное ( в разных запросах) соединение или фильтр по этому полю. А в принципе оптимизатор запроса сам построит временный индекс по этому полю.
Вот ,блин. Редактировать жутко неудобно и цвета выделения не работают.
я лично не стал бы рассчитывать на это неявное поведение оптимизатора, у его и других задач/приоритетов полно.
Если индекс все равно нужен, т.к. будет использоваться в фильтрах или соединениях, нужно задавать его явно!
КонецПериода вставил как двойной предохранитель.
Мне тут как то приходилось объяснять Шепоту , что такое оппонент и в чем его задача. Задача его "наводить критику". Вот я навожу.
Смотрел , смотрел текст запросов. Затем еще раз прочитал твои объяснения в статье.
Критика1. Если ты хочешь , чтобы кто-то что-то понял , то так алгоритмы не представляют и не офомляют. Нужен упрощенный текст запроса в теме и сквозной понятный пример ( с заполненными демнострационными таблицами в тексте)
Критика 2. Вложенные запросы в тексте призводят жуткое впечатление.
Давно пора перейти к временным таблицам. Легче рассматривать , проще искать ошибки и т.д. Уж сколько говорилось на эту тему и фирмой 1с и пользователями ИС...
Критика 3. Теперь по сути.
Теперь для меня, вне всякого сомнения, твой запрос по скорости проиграет слегка оптимизированной (почти тупой) выгрузке в таблицу значений и заполнения её необходимыми данными за один проход (подчеркиваю , вся выходная таблица будет получена за один проход).
Алгоритм этот и проще для понимания.
Но первая прелесть твоего алгоритма именно в том, что реализуя весь алгоритм в одном запросе - мы "отвязываемся от клиента" и передаем всю нагрузку вычислений на сервер баз данных.
Вторая прелесть в том , что для больших баз он оптимальнее алгоритма приведенного Евгением (мелкие запросы в цикле). Я даже предполагаю , что разница в скорости будет в немалые разы.
Критика 4. Дойдя до получение таблиц УвеличениеДолгаДень, Ув..месяц, Ув..Год, я не сомневался что последует дальше. Ан нет. Мне всерьез непонятно ,зачем так сложно ? Спорить тут бестолку. Алгоритм у тебя работатет.
Про оптимальный, на мой взгляд, алгоритм лучше самому писать статью.
Вот брошу пить - я за Вас возьмусь !
Если напишу - приглашу тебя и назначу самым злобным оппонентом.
Кстати, Игорь помнишь я тебе говорил про перепроведение по регистру партий - как получить все движения всех перепроводимых документов одним запросом ? И на чем споткнулся и все полетело коту под хвост ? Именно на этом : запросы с нарастающими итогами. Такое перепроведение - одним запросом все движения - уступало по быстродействию штатной обработке (с использованием таблицы значений) многократно.
И хотя задача перепроведения чуть навороченнее, но задаче в теме родственная. И суть та же как обойти медленный расчет нарастающих итогов.
и за один проход получить выходную таблицу. Вот по прежнему слабо верится , что он уступит запросу в этой теме.
Хотя можно сделать три запроса : Сравнить текущийдолг с оборотом за месяц - все попавшие выгрузить, остальные сравнить с оборотом за год и т.д
а еще посмотрите в технологическом журнале как генерируется запрос для таблицы ОстаткиИОбороты, ведь, как мы знаем, поле КонечныйОстаток - это как раз остаток нарастающим итогом. Да, кстати, никто не сказал про использование таблицы ОстаткиИОбороты, а ведь с помощью неё можно добиться желаемого результата.
Я считаю , что Таблицу ОстаткиИОбороты эффективно использовать в данной задаче не удастся. Ну.. так мало ли , что я считаю . Если думаешь, что из этой таблицы можно что-то выудить - пиши статью.
И я потянусь за тобой со своей статейкой : нет, товарищи , так делать нельзя. Глядишь , скука и пройдет...
Только условие Саши - весь алгоритм в одном флаконе (запросе) должно быть выполнено.
Реализация товаров и услуг №1 500р 2200р
Реализация товаров и услуг №2 1000р 1700р
Платежное поручение исходящее №1 -500р 700р
Реализация товаров и услуг №3 1200р 1200р
а в (69) это я скачал отчет из (44) и сформировал отчет, в чем смысл этого отчета, где там сумма нарастающим итогом, и зачем так много кода я так и не понял.
Контрагент Вася Пупкин имеет долг 100 рублей
Ему были отпушены две последние накладные
Накл 1 на 40 р.
накл 2 на 70 р.
Нужно получить таблицу
Контрагент Долг
Вася Пукин 100 р.
Накл 1 40р.
Накл 2 60р.Т.е список неоплаченных накладных .
См. текст запроса в статье :
Вначале мы найдем при помощи запроса таблицу
Документ Сумма НарастающийИтог
Накл1 40 40
Накл 2 70 110Затем исхитримся и опять запросом сраниваем долг 100 с колонкой накопленные итоги , "попадем " на накл 2 отбросим 10 рублей и запишем
Накл1 40
Накл 2 60 (63) Итоги то с нарастающим, но там все итоги, а нам нужны только по документам увеличивающим задолженность
С разными виртуальными таблицами есть ещё лажа с Границами, в таблице остатки нельзя задать условие не границу, её туда надо в виде параметра запихивать, а в ОстаткахИОборотах есть соответствующий параметр, который преобразовывает дату в границу. Вот тут и есть глобальная подстава для СКД... Штатным конструктором нельзя границу в запрос СКД передать, только с помощью кода. Поэтому когда быстро ваяешь запрос по виртуальной таблице Остатки в СКД, нужно помнить, что граничные значения не получишь.
Ага , вот нашел у тебя в условии соединения :
И (ВЫБОР
КОГДА ПериодыРегистратор.Период < УвеличениеРегистратор.Период
ТОГДА ИСТИНА
ИНАЧЕ ВЫБОР
КОГДА ПериодыРегистратор.Период = УвеличениеРегистратор.Период
ТОГДА ПериодыРегистратор.Регистратор <= УвеличениеРегистратор.Регистратор
ИНАЧЕ ЛОЖЬ
КОНЕЦ
КОНЕЦ) ПоказатьТакое выражение в условии соединения есть предложение оптимизатору запроса - отдохни , это не для тебя - мы будем тормозить ! и обращаться не к индексу ,а к каждой записи самой таблицы!
Чтобы дать хоть какой то шанс бедному оптимизатору , на мой осторожный взгляд, лучше написать :
И ( ПериодыРегистратор.Период < УвеличениеРегистратор.Период ИЛИ
ПериодыРегистратор.Период = УвеличениеРегистратор.Период И
ПериодыРегистратор.Регистратор <= УвеличениеРегистратор.Регистратор)1. Меню-Файл-Открыть
2. Выбираю тип файла: Внешняя обработка
3. что-то не вижу :o , в поле "Имя файла" набираю первые буквы и вот он, нажимаю открыть, а там пусто :o
Если открыть без фильтра или с правильным фильтром(Внешния отчет), то открывается все ОК :D
Еще раз. на 100 рублей долга нужно набрать накладных , которые были отпущены клиенту .
И сказать : вот вам список накладных, которые клиентом не оплачены.
Из этого списка неолаченных накладных мы выбираем по дате те накладные которые отстоят от текущей даты на компе более чем на N дней суммируем их и говорим - а вот это просроченный долг !
N - разрешенной количество дней просрочки долга.
а во-вторых в отчете из 44 выводится Регистратор, объясните мне как может получится, что долг у контрагента 100 рублей, а у документов сумма 70 и 40? Или этот отчет тоже не решает этой задачи?
Вася Пупкин Долг 100
Имеет документы :
Накл. 1 40
Накл 2 70
Платеж -10 Нужно узнать какие накладные клиентом не оплачены и на какую сумму каждая накладная не оплачена (см. (85) вторая таблица) ?
И ты получишь :
Накл1 40
Накл 2 60 1. База у Саши 120Гб.
2. Саша ни в какую не согласен кодировать и настаивает на том , что весь алгоритм должен умещаться в одном запросе. (вся нагрузка , как и в задаче получения всех движений регистра партий при перепроведении, ляжет на сервер базы данных).
3. Самое смешное в том , что сейчас я понимаю , что он прав.
И я готов отказаться от своих предложений как неоптимальных.
Эти предложения предполагают кодинг.
"Подведем итоги . Нарастающие." - о том каким должен быть текст оптимального запроса в данной задаче . В статье - Текст запроса и сопровождающие его иллюстрации в виде таблиц.
Приглашаю быть злобным оппонентом. Приглашаю также Игоря и Артура.
Через 2-3 дня сообщу дату публикации.
Задачи получения всех движений расходных докуметов по регистру партий за период
Действительно , в задаче просроченного долга для каждого контрагента :
S - сумма долга
С1,С2...Сk - последовательность сумм всех документов отгрузки.
Требуется найти такую последовательность С1,С2...Сn, чтобы
S = C1+C2+...+Cn
Грубо говоря , набираем накладные на сумму долга.
А если вместо S взять последовательность S1,S2...Sk (суммы документов прихода), то тогда получим задачу получения всех движений по регистру партий при перепроведении расходных документов.
И эта задача решается тоже при помощи нарастающих итогов.
И тоже одним пакетом запросов , набранном в конструкторе.
Момент времени упорядочивает документы внутри секунды жестким, "случайным" и неуправляемым образом. Какие основания полагаться на этот порядок при решении о порядке погашения документов? Опять же, если бы случайность была бы "мягкой", то в среднем односекундные документы погашались предложенным мною способом.
И, далее, предлагаемое решение не "пасует" в этой ситуации, а просто рассматривает односекундные отгрузки как единые документы с точки зрения взаиморасчетов. Это очень просто объяснить менеджерам. Они видят все (а не один произвольно выбранный) частично оплаченные документы и их общую сумму.
А если поместить результат в таблицу значений и скормить эту таблицу значений, как набор данных СКД? - кто-нибудь пробовал так делать и замерять на сколько это решение работает быстрее, и что в этом случае происходит с использованием оперативной памяти?
Вы можете заказать платную консультацию или разработку у автора. Будет создан приватный заказ на «Бирже заказов» для автора.
№ 58966
Создание 19.10.09 00:08
Обновление 19.10.09 00:00
Просмотры 78801
Загрузки 0
Рейтинг
76
Комментарии 119
Код открыт Не указано
Рубрики Запросы
Кому Разработчик
Тип файла Нет файла
Платформа 1С:Предприятие 8
Конфигурация 1C:Бухгалтерия
Операционная система Не имеет значения
Страна Россия
Отрасль Не имеет значения
Налоги Не имеет значения
Вид учета Не имеет значения
Доступ к файлу Бесплатно (free)