0. Ish_2 1031 24.11.09 14:06 Сейчас в теме

Подведем итоги. Нарастающие.

Как одним пакетом запросов получить таблицу просроченных долгов контрагента ?
Подробное иллюстрированное построение пакета запросов.




Перейти к публикации

Комментарии
Избранное Подписка Сортировка: Древо
122. Ish_2 1031 11.12.09 22:56 Сейчас в теме
(112) Для меня в первую голову непонятно почему в 8.х для временных таблиц невозможны команды создания и модификации таблиц (create table, update). Целостность основной базы при реализации такой возможности не нарушается . И как бы тогда выглядела задача нарастающих итогов и просроченных долгов ?
В чем тут дело сказать трудно. Ведь и сами временные таблицы - тоже совершенно очевидная вещь - появились только через 4(!) года в 8.1, а до этого в 8.0 писались километровые вложенные запросы.
119. hogik 428 11.12.09 16:12 Сейчас в теме
(111)
"Я же считаю , что это очень дурной тон тогда , когда можно обойтись агрегатными командами или запросами."
Именно об этом я и сказал в той юмористической теме. Т.е цель - писать красивые "запросы" (алгоритмы)... ;-) И "суть этого шаблона в том ", что за красотой не видна сама задача и пути её решения. Повторю, что "проблемы", обозначенной в Вашей статье, вообще не существует при наличии подходящих инструментов. Очень жаль, что "1С 8.х" таких инструментов не предоставляет... :-(
P.S. Не ставлю минус на данную публикацию, т.к. минус надо ставить не на Вашу публикации, а на "1С 8.х".
108. alexqc 11.12.09 11:05 Сейчас в теме
(106) Акцентирую Ваше внимание еще раз: в начальной постановке пропущено (точнее, указано вне основной части и как то вскользь) критическое условие: мы не просто строим н/итоги, мы ФИЛЬТРУЕМ по н/итогу. В таком случае - да, от того где выполняется построение итогов зависит объем пришедшей на клиента выборки, и клиент начинает иметь значение. Но, ИМХО, это все-таки очень частный случай - обычно н/итоги нужны "как есть". Точно также как и просто суммы - случаи, когда производится фильтрация по колонкам sum(), сравнительно немного (и чаще всего это having sum()<>0) - обычно нечто из серии "выбрать крупных клиентов", что уж точно не в оперативной работе применяется.

Теперь по поводу объемов.

Во-первых, не могу представить реальной ситуации, где действительно нужно обработать такую выборку. Конечный потребитель (человек) просто не воспримет "миллион контрагентов". Т.е. наверняка "масштаб" выборки можно будет укрупнить, что-то свернув. А если надо не по всем, а по одному/нескольким - то же самое, у вас 300 млн доков на 1 млн контрагентов - всего 300 доков на контрагента, не так уж и много.

Во вторых, при таких объемах для подобных задач рулят уже другие системы (а-ля OLAP) и другие подходы (промежуточные хранилища данных, заранее свернутая аналитика и итоги по периодам), которые выходят за рамки 1С.

Ну и в третьих, такие объемы, да на 1С - это опять же исключение. Штучные экземпляры. В массе для обычной фирмы-пользователя 1С база 20 гиг - это уже "ого-го". А там где больша - часто практикуется "закрытие периода".
110. alexqc 11.12.09 11:35 Сейчас в теме
+ к (108) да, и забыл еще раз упомянуть - циклы ведь можно делать и на сервере! Правда, не знаю можно ли это делать через 8ку, подозреваю что нет.
123. Ish_2 1031 11.12.09 23:19 Сейчас в теме
(110) В языке запросов 1с "цикла" точно нет.
115. Ish_2 1031 11.12.09 15:19 Сейчас в теме
(108)
"Акцентирую Ваше внимание еще раз: в начальной постановке пропущено (точнее, указано вне основной части и как то вскользь) критическое условие: мы не просто строим н/итоги, мы ФИЛЬТРУЕМ по н/итогу. В таком случае - да, от того где выполняется построение итогов зависит объем пришедшей на клиента выборки, и клиент начинает иметь значение."

Честно говоря, не очень понял.
В приложении написано , что нарастающие итоги для каждой записи (СуммаДо,СуммаПосле) строятся для того, чтобы определить запись для которой СуммаДо < ИскомыйПараметр <= СуммаПосле. Судя по всему Вы под этим понимаете фильтрацию по нарастающим итогам.

НО. При 2 варианте в начале статьи (ish_2) никакой фильтрации нет вовсе.
Делается запрос по всем движениям всех контргаентов и используется выборка Запрос.Выполнить().Выбрать(). И затем сканируя двухуроневую (контргаент,движения) выборку в цикле будем накапливать итог (сумма всех пред.движений) для каждого контргаента и сранивать этот итог с текущим долгом каждого контрагента.
116. anig99 11.12.09 15:26 Сейчас в теме
(108) по поводу объемов. Действительно свыше 100 контрагентов уже сложно воспринимать - для этого нужны агрегированные показатели. Например, просроченная дебиторка(не буду углублятся, но для этого тоже нужны нарастающие итоги) по менеджерам. Выходная таблица небольшая, но анализируемый объем данных огромный.
117. Ish_2 1031 11.12.09 15:36 Сейчас в теме
(108) В целом согласен.
Но интересен эксперимент , который всё расставит по местам : с какого размера таблицы вариант 3(Anig99) превзойдет вариант 2 (Ish_2) по быстродействию ?

1. Пока установлен только факт Вариант 1( Eugeneer) значительно проигрывает по быстродействию Варианту 3(Anig99) на базе 120Гб.
Информация о этом факте представлена Anig99.

2. По информации того же Anig99, времена выполнения Варианта2(ish_2) и Варианта 3(Anig99) на этой же базе 120Гб относятся как 5:1
118. anig99 11.12.09 15:41 Сейчас в теме
(117) я уже в личке говорил, теперь так озвучу, так как не успел к желаемому сроку... Пишу сейчас в свободное время обработку для тестирования времени получения нарастающих итогов разных подходов для разных объемов данных.
120. Ish_2 1031 11.12.09 16:34 Сейчас в теме
(118),(119)
Очень хорошо , что ты пишешь тест сравнивающий разные подходы !
Текущей статье не хватает замеров производительности , о которой писал еще Игорь в (21) . Без такого фактического сравнения можно еще долго спорить о "красивости" и "некрасивости" алгоритмов.

С Вами , Владимир , я опять не согласен. И ничего такого в минусе от Вас на текущую тему не вижу.
101. anig99 10.12.09 14:05 Сейчас в теме
(99) Самый оптимальный для чего????
Вот пример...
Для бомжа жить под теплоцентралью и бутылки собирать - оптимальный вариант... Тепло, относительно сухо, почти каждый вечер можно собрать на бутылку и закусь... Зашибись. Самый оптимальный вариант - для бомжа...
А вот попробуйте таким образом собрать на Ламборджини??? Мало того, что бутылки собирать будете пол жизни, так вам ещё нужно найти кто бомжику без паспорта Ламборджини продаст... так ещё и ездить как-то надо научится, на бензин опять-таки.
С другой стороны, нафуа бомжу Ламборджини??? Ведь большинство бомжуют не из-за отсутствия способностей, а из-за нежелания работать и/или удовлетворения текущим положением вещей.
А положение вещей, конечно, может быть разным... Может климатические условия очень хорошие - бананы там всякие, кокосы... или бомжик совсем маленький и Ламборджини ему игрушечной хватает....
Тут сразу столько оптимумов появляется... Ух...

Таким образом, если в процессе работы Вас устраивает время получения данных с нарастающими итогами, то пользуйтесь текущим методом. Но это ВАШ оптимум.

А мы здесь обсуждаем как БЫСТРО заработать на Ламборджини, а не как легко прожить.
102. Ish_2 1031 10.12.09 14:17 Сейчас в теме
104. alexqc 146 10.12.09 19:22 Сейчас в теме
(101) Аналогии хороши для иллюстрации, для доказательства - зло.
Ламборджини - это скорее к САПу.
Встречный вопрос - у Вас очевидно, она уже есть?

А про оптимальность я вполне аргументировал: цикл - линейная трудоемкость, пересечение таблиц - в пределе квадратичная. Говоря Вашими словами - мы покупаем Ломбарджини за ее обычную цену, но предварительно еще оплатив детали, труд сборшиков, механиков и продавца.
113. alexqc 11.12.09 13:52 Сейчас в теме
А вот как можно (с извратом) сделать на MSSQL

--наши исходные данные
create table #t(i int,s int)
insert into #t values (1,100)
insert into #t values (2,200)
insert into #t values (4,400)
insert into #t values (3,300)
insert into #t values (5,500)
select * from #t

-- наш результат
create table #tt(i int primary key,s int,ss int)
insert into #tt(i,s) select i,s from #t


/* А вот тут прикол - обработка таблицы будет вестись в порядке ее
первичного ключа. Вот такой неявный цикл.
Это не специфицировано в стандарте, это особенность реализации от MS.*/

declare @d int
set @d=0
update #tt set @d=@d+s, ss=@d

--окончательный результат
select * from #tt
114. Ish_2 1031 11.12.09 14:03 Сейчас в теме
(113) Странно. На почту какие-то приходят соощения , какие-то нет. Отвечу чуть позже.
124. Ish_2 1031 11.12.09 23:28 Сейчас в теме
/* А вот тут прикол - обработка таблицы будет вестись в порядке ее
первичного ключа. Вот такой неявный цикл.
Это не специфицировано в стандарте, это особенность реализации от MS.*/
declare @d int
set @d=0
update #tt set @d=@d+s, ss=@d
--окончательный результат
select * from #tt


(113) Виноват , не понял в чем прикол ? Если мы создали tt с первичным ключом , то ,разумеется, модификация таблицы tt по команде
update #tt set @d=@d+s, ss=@d
будет вестись в порядке ее первичного ключа. Тут есть что-то прикольное ?
125. alexqc 146 14.12.09 11:30 Сейчас в теме
(124) В SQL не специфицирован порядок обработки данных. Вообще классически таблицы рассматриваются как "НЕУПОРЯДОЧЕННЫЙ" набор. ПК (если есть) должен однозначно идентифицировать запись, но не является обязательным указанием порядка обработки. Обработка данных в порядке ПК - это расширение стандарта, сделанное в отдельных реализациях, но не факт что аналогичная конструкция будет работать в другом SQL-сервере. И, наконец, такая конструкция противоречит "декларативному" характеру языка.

(122) Серьезно??? В 8.1 нельзя менять врем. таблицы??? А как они тогда вообще делаются - только через select into? А индексы на поля ставятся?
(Может, это просто разработчики вообще ничего кроме select не реализовали - а неизменение врем. таблиц - только следствие)
Я, признаться, думал что 8.1 позволяет делать все что можно с SQL.

(122) (123) Наверно нам надо четко указывать что имеем ввиду - 77 или 8. В 77 1С++ позволяет послать запрос в любом виде, но получает только 1-й набор пакета (таковы ограничения механизма семерки). Покольку я не работаю с 8кой, то не знаю ее возможностей и ограничений.
В любом случае, если в 8ке столько ограничений - толку от пакета никакого (точнее, пакет ничем не лучше последовательного выполнения неск. запросов).

Но речь шла не только о том, что нельзя получить результаты пакета кроме первого, а о том что вообще нельзя управлять выдачей результата. Т.е. если у меня в пакете есть "промежуточные" select,update,insert - то в результат попадет это все, хотя мне нужен только самый последний select. А нахрена лишние данные гонять? А уж тем более - зачем мне результат допустим insert'а?.



126. Ish_2 1031 14.12.09 11:56 Сейчас в теме
(125)
Серьезно??? В 8.1 нельзя менять врем. таблицы??? А как они тогда вообще делаются - только через select into? А индексы на поля ставятся?
(Может, это просто разработчики вообще ничего кроме select не реализовали - а неизменение врем. таблиц - только следствие)

Ага . Именно так.
К тому же сама возможность работы в 8.1 с временными таблицами ( в 8.0 этого не было) подавалось фирмой 1с - как большое достижение.
128. y-str 53 25.08.11 10:04 Сейчас в теме
Добрый день!

Создал новую публикацию (http://infostart.ru/public/88999/) с возможным альтернативным алгоритмом.
Милости прошу комментировать :)

---
С уважением,
Юрий Строжевский
129. ZLENKO 06.09.12 15:20 Сейчас в теме
Насколько я понимаю, предложенный тут вариант годится только для "размазывания" остатка долга на последние документы. На текущий момент мне интересен вариант решения похожей задачи, но чтобы было видно какой документ каким документом "закрылся". Это нужно для отчета по платежной дисциплине - чтобы было видно насколько своевременно происходили оплаты. Пока что решил задачу так: 1) Запрос к базе с получением дебетовых и кредитовых оборотов с детализацией до регистратора; 2) Цикл по "сопоставлению" дебета и кредита; 3) Запись результата сопоставления в регистр сведений; 4) Построение различных отчетов (в т.ч. по просроченной дебиторке) по регистру сведений.
Запрос получающий данные не совсем оптимальный для данной задачи, но взял его готовый из своего отчета по просроченной дебиторке - получает данные секунд 15. Цикл разнесения отрабатывает очень быстро - порядка 3 секунд. Получаем набор записей регистра сведений порядка 130 тыс строк - пишется долго - около 20 секунд (наверное сервер все таки не очень быстрый у клиента).
130. ZLENKO 06.09.12 15:25 Сейчас в теме
(129) Приведенные замеры времени для вызова на клиенте. На самом деле все это вынес в регламентное задание - время выполнения на стороне сервера не засекал (по идее должно быть быстрее т.к. не надо данные туда-сюда гонять). Но все же интересно можно ли решить не циклом а запросом ?
P.S.: Данные по оплаченности документов реализации также потом используются для отчета по оплаченной реализации с детализацией до номенклатуры.
131. Ish_2 1031 08.09.12 12:23 Сейчас в теме
(129) С точки зрения программиста задача просроченного долга может иметь несколько вариантов решения.
Варианты эти могут быть сложные или простые , плохие или хорошие..
Но с точки зрения Заказчика ,как мне недавно объяснили, единственным правильным подходом
является следующий : организовать учет по расчетным документам, т.е использовать 3 субконто на счете 62 в БП2.0. Все проблемы тогда решаются сами собой.
132. ZLENKO 09.09.12 21:42 Сейчас в теме
(131) Самым правильным вариантом несомненно является вариант учета по расчетным документам. Однако заказчик далеко не всегда хочет как правильно. Когда я был моложе, я старался убедить заказчика как именно правильно. Однако с возрастом появился вопрос "зачем". Сейчас я стараюсь дать заказчику именно то что он хочет и совершенно неважно (ни для него ни для меня) правильно это или нет. В итоге все остаются довольны (и заказчик и я) :-)
133. Ish_2 1031 09.09.12 23:44 Сейчас в теме
(132) Я еще молод,поэтому не упускаю случая , чтобы сказать Заказчику как правильно.
Оставьте свое сообщение
Новые вопросы с вознаграждением
Автор темы объявил вознаграждение за найденный ответ, его получит тот, кто первый поможет автору.

Вакансии

Консультант-аналитик 1С
Москва
Полный день

Консультант ERP-систем
Москва
Временный (на проект)

Программист 1С
Москва
зарплата от 140 000 руб.
Полный день

Программист 1С
Санкт-Петербург
Полный день

Программист 1С
Нижневартовск
зарплата от 60 000 руб.
Полный день