Использование нарастающих итогов в партионном учете и не только

25.08.11

Разработка - Математика и алгоритмы

Данный материал является иллюстрацией способов работы с запросами, использующими методику вычисления «нарастающих итогов». Также в данной статье рассматриваются вопросы практического использования запросов такого рода при партионном учете и расчете задолженностей.

Фактически в данной статье рассматриваются альтернативы запросам, приведенным в статьях http://infostart.ru/public/61295/ и http://infostart.ru/public/68225/.

Полный текст статьи можно также найти на http://nashe1c.ru/materials-view.jsp?id=383.

Скачать файлы

Наименование Файл Версия Размер
Использование запросов с нарастающим итогом.doc
.doc 129,50Kb
79
.doc 129,50Kb 79 Скачать

См. также

Метод Дугласа-Пойкера для эффективного хранения метрик

Математика и алгоритмы Платформа 1C v8.2 Конфигурации 1cv8 Россия Абонемент ($m)

На написание данной работы меня вдохновила работа @glassman «Переход на ClickHouse для анализа метрик». Автор анализирует большой объем данных, много миллионов строк, и убедительно доказывает, что ClickHouse справляется лучше PostgreSQL. Я же покажу как можно сократить объем данных в 49.9 раз при этом: 1. Сохранить значения локальных экстремумов 2. Отклонения от реальных значений имеют наперед заданную допустимую погрешность.

1 стартмани

30.01.2024    1754    stopa85    12    

33

Алгоритм симплекс-метода для решения задачи раскроя

Математика и алгоритмы Бесплатно (free)

Разработка алгоритма, построенного на модели симплекс-метода, для нахождения оптимального раскроя.

19.10.2023    4420    user1959478    50    

34

Регулярные выражения на 1С

Математика и алгоритмы Инструментарий разработчика Платформа 1С v8.3 Мобильная платформа Россия Абонемент ($m)

Что ж... лучше поздно, чем никогда. Подсистема 1С для работы с регулярными выражениями: разбор выражения, проверка на соответствие шаблону, поиск вхождений в тексте.

1 стартмани

09.06.2023    7464    4    SpaceOfMyHead    17    

56

Модель распределения суммы по базе

Математика и алгоритмы Платформа 1С v8.3 Россия Абонемент ($m)

Обычно под распределением понимают определение сумм пропорционально коэффициентам. Предлагаю включить сюда также распределение по порядку (FIFO, LIFO) и повысить уровень размерности до 2-х. 1-ое означает, что распределение может быть не только пропорциональным, но и по порядку, а 2-ое - это вариант реализации матричного распределения: по строкам и столбцам. Возможно вас заинтересует также необычное решение этой задачи через создание DSL на базе реализации текучего интерфейса

1 стартмани

21.03.2022    7855    7    kalyaka    11    

44

Изменения формата файлов конфигурации (CF) в 8.3.16

Математика и алгоритмы Платформа 1С v8.3 Бесплатно (free)

Дополнение по формату файлов конфигурации (*.cf) в версии 8.3.16.

16.12.2021    4446    fishca    13    

36

Интересная задача на Yandex cup 2021

Математика и алгоритмы Бесплатно (free)

Мое решение задачи на Yandex cup 2021 (frontend). Лабиринт. JavaScript.

12.10.2021    8839    John_d    73    

46

Механизм анализа данных. Кластеризация.

Математика и алгоритмы Анализ учета Платформа 1С v8.3 Анализ и прогнозирование Бесплатно (free)

Подробный разбор, с примером использования, встроенного механизма кластеризации 1С.

31.08.2021    7806    dusha0020    8    

70
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. Ish_2 1104 25.08.11 10:18 Сейчас в теме
За рекламу - спасибо.
Пробежал мельком . Пока замечание :
в статье никак не отмечено : использование нарастающих итогов "в лоб"
(т.е. использвание содинения по неравенству в запросе) для больших таблиц приведет к "падению" всего алгоритма.

По оформлению : лучше оформить статью на ИС как полагается , а не предлагать файл со статьей к скачиванию.
2. Поручик 4670 25.08.11 10:43 Сейчас в теме
Мне тоже лень скачивать файло
3. y-str 60 25.08.11 10:49 Сейчас в теме
Формально эта статья опубликована на http://www.nashe1c.ru/materials-view.jsp?id=383 (если кому "лень качать файло" :) ).
Позже еще покопаюсь здесь - не нашел сразу как вставлять в статью картинки при публикации на этом сайте.

To Ish_2: аргументируйте, пожалуйста, как именно может повлиять размер таблиц на работу этого алгоритма?
4. Ish_2 1104 25.08.11 10:57 Сейчас в теме
Пока по мелочи . Что бросилась в глаза .
В объяснении текста запроса
SELECT
 tab1.Номенклатура,
 tab1.Партия,
 ( SUM( ISNULL( tab2.КоличествоОстаток, 0 ) ) + MAX( tab1.КоличествоОстаток ) ) AS НарастающийИтог ...

Написано :
вместо простого прибавления к сумме остатков по предыдущим партиям текущего остатка мы прибавляем функцию «MAX» от текущего остатка. Это необходимо по правилу использования группировок в запросе – все данные, не вошедшие в поля группировки, должны выражаться через функции языка запросов.

Ошибка. То есть использование функции "МАХ" в данном случае не является необходимым
Правильно :
SELECT
 tab1.Номенклатура,
 tab1.Партия,
  SUM( ISNULL( tab2.КоличествоОстаток, 0 ) ) +  tab1.КоличествоОстаток  AS НарастающийИтог ...
5. y-str 60 25.08.11 10:59 Сейчас в теме
На всякий случай уточню, что представленный в статье вид запроса как-раз и позволяет сильно ограничить количество записей в результирующем наборе. Сам по себе запрос может быть транслирован в SQL без изменений и, тем самым, позволяет работать с большими начальными таблицами, получая только необходимые выходные данные (без дополнительных обработок в последующих запросах или в текстах модулей).
6. y-str 60 25.08.11 11:02 Сейчас в теме
Ish_2 пишет:

Пока по мелочи . Что бросилась в глаза .

В объяснении текста запроса



О как :) А что, так будет работать, без MAX/MIN? Проверяли? :)
7. Ish_2 1104 25.08.11 11:14 Сейчас в теме
(6) В конфигурации прикрепленной к теме "ФИФО для любопытных" http://infostart.ru/public/68225/
использован именно такой запрос без МАХ.
Почему для больших таблиц соединение по неравенству работает оч. медленно можно прочитать в теме "Подведем итоги.Нарастающме" .
Можно убедиться в этом самостятельно : создайте таблицу tab1 с количеством записей 1 000 000 .
Запустите Ваш запрос - соединение по неравенству tab1 "сама с собой" засеките время. И всё поймете... назавтра.
9. y-str 60 25.08.11 11:24 Сейчас в теме
(7)В упомянутой конфигурации используется конструкция вида:

SELECT
Поле1,
СУММА( Поле2 ) + Поле1
FROM
GROUP BY Поле1

Здесь да, наличие MAX/MIN не нужно. Но в моем запросе используется поле, по которому отсутствует группировка. Так что это поле ОБЯЗАТЕЛЬНО должно включаться в выражения запроса в виде функции языка запросов. Насчет скорости исполнения - я проведу такие испытания, но еще раз скажу, что суммирование или простое сравнение по индексу для SQL выполняется очень быстро. Размер таблиц в миллион записей никак не влияет на скорость исполнения. Возможно здесь будет влиять сама 1С, но это уже другой вопрос.
12. Ish_2 1104 25.08.11 11:58 Сейчас в теме
(9) Мда.. Зачем спорить ? Вы попробуйте.
Вот Ваш вариант с "МАХ" :
SELECT
 tab1.Номенклатура,
 tab1.Партия,
 ( SUM( ISNULL( tab2.КоличествоОстаток, 0 ) ) + MAX( tab1.КоличествоОстаток ) ) AS НарастающийИтог
FROM РегистрНакопления.ОстаткиНоменклатуры.Остатки AS tab1
LEFT JOIN РегистрНакопления.ОстаткиНоменклатуры.Остатки AS tab2
ON ( tab1.Номенклатура = tab2.Номенклатура ) AND ( tab1.Партия > tab2.Партия )
GROUP BY tab1.Номенклатура, tab1.Партия;

Вот мой без "МАХ":
SELECT
 tab1.Номенклатура,
 tab1.Партия,
 SUM( ISNULL( tab2.КоличествоОстаток, 0 ) ) +  tab1.КоличествоОстаток   AS НарастающийИтог
FROM РегистрНакопления.ОстаткиНоменклатуры.Остатки AS tab1
LEFT JOIN РегистрНакопления.ОстаткиНоменклатуры.Остатки AS tab2
ON ( tab1.Номенклатура = tab2.Номенклатура ) AND ( tab1.Партия > tab2.Партия )
GROUP BY tab1.Номенклатура, tab1.Партия;


Ну как ? Получилось ?
13. y-str 60 25.08.11 12:03 Сейчас в теме
(12) Конечно НЕТ, не получилось! :) Не позорьтесь, почитайте документацию, попробуйте сами подобные запросы. Это общее правило SQL запросов и оно незыблемо :)
14. Ish_2 1104 25.08.11 12:07 Сейчас в теме
(13) Случай тяжелый , запущенный.
Жаль , что обсуждение так печально закончилось.
15. y-str 60 25.08.11 12:13 Сейчас в теме
(14) Нет, я правда попробывал :) Честно-честно! :) 1С мне написало "Поле не входит в группу "tab1.КоличествоОстаток"". На всякий случай: платформа 8.2.14.528
17. Ish_2 1104 25.08.11 12:46 Сейчас в теме
(15) Платформа 8.2.13.205.
Проверена в работе конфигурация http://infostart.ru/public/68225/ . Содержит запрос:
               |ВЫБРАТЬ
               |	Приход.Период,
               |	Приход.МоментВремени,
               |	Приход.Партия,
               |	Приход.Номенклатура,
               |	Приход.Количество,
               |	Приход.Сумма,
//
               |	СУММА(Приход1.Количество) - Приход.Количество КАК КоличествоДо, // Внимание ! Приход.КОличество без МАХ
//
               |	СУММА(Приход1.Количество) КАК КоличествоПосле
               |ПОМЕСТИТЬ НарПриход
               |ИЗ
               |	Приход КАК Приход
               |		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Приход КАК Приход1
               |		ПО Приход.Номенклатура = Приход1.Номенклатура
               |			И Приход.МоментВремени >= Приход1.МоментВремени
               |
               |СГРУППИРОВАТЬ ПО
               |	Приход.Партия,
               |	Приход.Период,
               |	Приход.МоментВремени,
               |	Приход.Номенклатура,
               |	Приход.Количество,
               |	Приход.Сумма
               |;
Показать


Ищите ошибку у себя.
19. y-str 60 25.08.11 12:49 Сейчас в теме
(17) Вот! А теперь просто уберите строчку "Приход.Количество" из блока "СГРУППИРОВАТЬ ПО" :) Еще раз: у меня используется поле, НЕ входящее в группировку.
23. Ish_2 1104 25.08.11 12:54 Сейчас в теме
(19) ,(20) Правильно ! Пост (12) неверен !
25. y-str 60 25.08.11 12:57 Сейчас в теме
(23) Супер! Очень рад, и надеюсь на дальнейшее продотворное сотрудничество! :)
26. Ish_2 1104 25.08.11 12:59 Сейчас в теме
(25) Ухожу на "больничный".
20. alexk-is 6533 25.08.11 12:49 Сейчас в теме
(17) :)

|СГРУППИРОВАТЬ ПО
| Приход.Партия,
| Приход.Период,
| Приход.МоментВремени,
| Приход.Номенклатура,
| Приход.Количество,
| Приход.Сумма


Вот где собака порылась :)
16. y-str 60 25.08.11 12:46 Сейчас в теме
(14) Я тут подумал: может Вы просто перепутали конструкции запроса? То есть существует такая конструкция как "ИТОГИ Поле1, СУММА(Поле2) ПО Поле1". Вот там в самом тексте запроса функции употреблять не надо - они применяются только в итогах. На всякий случай: по-английски это пишется как "TOTALS Поле1, SUM(Поле2) BY Поле1".
8. alexk-is 6533 25.08.11 11:16 Сейчас в теме
(0) :o

Так писать нельзя. Это же деление на 0
END * MAX( ISNULL( tab1.СуммаОстаток, 0 ) ) / MAX( ISNULL( tab1.КоличествоОстаток, 0 )
Луна5; +1 Ответить
10. y-str 60 25.08.11 11:24 Сейчас в теме
alexk-is пишет:

(0)



Так писать нельзя. Это же деление на 0


О, спасибо за комментарий! Учту :)
11. y-str 60 25.08.11 11:38 Сейчас в теме
(10) Исправил в статье на nashe1c, послал на модерацию. Сейчас и здесь добавлю еще один "CASE" в запрос.
Еще раз спасибо за указание на ошибку!
18. anig99 2843 25.08.11 12:47 Сейчас в теме
Я хотел бы внимание обратить на другую ошибку. В запросе оперируют данными виртуальной таблицы Остатки, что методологически неверно, т.к. остатки - это УЖЕ результат расчета с нарастающими итогами. И использование остатков в запросе с нарастающими итогами чрезвычайно ограничено.

Пока я не вижу новизну в статье, а только ошибку.

Такое объединение в запросе существенно ограничено количеством объединяемых записей.


1
2 > 1
3 > 1 + 2
4 > 1 + 2 + 3
5 > 1 + 2 + 3 + 4


в итоге получаем таблицу

1
2 1
3 1
3 2
4 1
4 2
4 3
5 1
5 2
5 3
5 4

Вместо 5 изначальных записей, получили 11. И прогрессия эта даже не геометрическая.
ildarovich; +1 Ответить
22. y-str 60 25.08.11 12:53 Сейчас в теме
(18) Про "неправильное методологическое поведение" я комментарий опущу. А вот насчет "геометрической прогрессии": в запросе нет объединения "все со всеми", соединение с "правой" таблице нужно только для вычисления функции суммы по остаткам.
27. anig99 2843 25.08.11 12:59 Сейчас в теме
(22) Сумма остатков! Это фигня получится.
Нач.ост = 0
Приход 10 Остаток = 10
Приход 11 Остаток = 21
Приход 5 Остаток = 26
Расход 1 Остаток = 25


Теперь нарастающий итог для последней строки с суммой остатков будет.... пырым-пым-пым ---- 10 + 21 + 26 = 57... фигня какая-то.
29. y-str 60 25.08.11 13:04 Сейчас в теме
(27) Эээть, вот здесь опять подробнее: движения имеют и "приход", и "уход". Так что расход добавляем с отрицательным знаком :)
32. anig99 2843 25.08.11 13:08 Сейчас в теме
(29) в регистре накопления есть Вид движения Приход и Расход. Знак при этом не меняется. Это в запросе можно получить уже Приход = Количество, а Расход = Количество*-1 или в две отдельные колонки. Знак тут не принципиален. Главное невразумительность сложения ОСТАТКОВ.
33. y-str 60 25.08.11 13:11 Сейчас в теме
(32) Для меня понятие "остаток" представляет собой разность между приходом и расходом. Всегда считал это общепринятым :)
34. alexk-is 6533 25.08.11 13:14 Сейчас в теме
(32) Тут хитрость методологии.
Складываются остатки не по операциям движений по регистрам, а остатки по партиям. Т.е. для списания нужно набрать пул списываемых партий и, собственно, всё.
Простая задачка. Не нужно усложнять.

См. (18)
Пока я не вижу новизну в статье
35. y-str 60 25.08.11 13:18 Сейчас в теме
(34) Конечно, ничего сложного! Просто мне было нужно, чтобы все вычислялось в рамках одного запроса, а не 7-ми как в http://infostart.ru/public/61295/. Я долго копался в Интернете, думал, что кто-то ведь наверняка должен был до этого додуматься - не нашел. Если есть ссылки на другие варианты решения задач, описанных в моей статье - буду очень благодарен!
41. anig99 2843 25.08.11 13:33 Сейчас в теме
(35) решение "в лоб" опубликовано на мисте уже давно. Я ещё повторю, ничего нового, кроме непонятного практического значения остаток по партии + сумма остатков партий до него. Хотя нет. Понял. Новизны нет. Всё тот же запрос в "лоб"

7 запросов нужно для оптимизации расчетов.
42. y-str 60 25.08.11 13:36 Сейчас в теме
(41) А можно ссылку на "решение в лоб" на мисте?
37. anig99 2843 25.08.11 13:27 Сейчас в теме
(34) не понимаю, какое практическое значение информации о остатке партии + сумма всех остатков партии до него?
39. alexk-is 6533 25.08.11 13:32 Сейчас в теме
(37) Посчитать сколько ещё положить в ведерко, пока ведерко не наполнится :)
40. y-str 60 25.08.11 13:33 Сейчас в теме
(37) Это, собственно, нарастающий итог остатка :) На определенном значении он превысит необходимое количество для списания и искомый список партий для списания будет готов.
30. alexk-is 6533 25.08.11 13:06 Сейчас в теме
(27) Это всё правильно. С остатками всё впорядке.
28. anig99 2843 25.08.11 13:03 Сейчас в теме
(22) а про объединение...Вот именно, что ВЫЧИСЛЕНИЕ. Для каждой из 5 записей будет производится свой расчет суммы с увеличением числа слагаемых.
т.е. будет не 1+2+3+4+5 = 5 действий сложений, как если это делать с помощью цикла в коде, а будет 11 действий сложений. И число операций сложений будет расти ОЧЕНЬ быстро.
31. y-str 60 25.08.11 13:07 Сейчас в теме
(28) Скажем так: подсчет суммы по любому числовому полю любой SQL таблицы с помощью запроса и функции SUM() вычисляется в разы быстрее, чем с помощью перебора всех строк и дальнейшего подсчета суммы с помощью любых алгоритмов. Я придерживаюсь этого мнения.
36. anig99 2843 25.08.11 13:22 Сейчас в теме
(31) Вопрос в том, что sum() будет вызываться столько раз, сколько записей в таблице. И каждый раз ему для расчетов будет передаваться такое число все большее число записей. В отличие от этого подхода, в цикле можно хранить предыдущий итог и прибавлять уже к нему (в sql это тоже можно организовать, но речь идет о запросе 1с, которые не умеет делать такого). В результате наступит такой момент, когда время выполнения Sum() с n записей будет выполнятся дольше, чем сложение двух цифр ПромежуточныйИтог + ТекущееЧисло в очередной итерации цикла. Это одна сторона. Другая сторона, что вообще время выполнения запроса 1с СУЩЕСТВЕННО увеличится. Проблема такого подхода в запросе, что вычисления для каждой записи каждый раз выполняеются ЗАНОВО с возрастающей нагрузкой на выч.ресурсы. В коде же нагрузка постоянна (ну кроме, увеличения объема памяти под хранения итогов).
Запрос "в лоб" выигрывает на маленьких объемах данных, цикл на больших. Но они оба проигрывают оптимизированному алгоритму запроса 1с или прямому запросу sql с организацией цикла прямо в запросе.
38. y-str 60 25.08.11 13:29 Сейчас в теме
(36) Не согласен! Использование "курсоров" вместо функций языка запросов - основная проблема производительности. Кто-то здесь уже делал тестовую базу под нарастающие итоги и проверял скорость работы запросов. Я поищу кто это был и постараюсь представить документальные доказательства.
24. y-str 60 25.08.11 12:55 Сейчас в теме
(21) Статью я читал, спасибо за развернутый материал!
43. y-str 60 25.08.11 14:34 Сейчас в теме
Приведу преимущества приведенного в моей статье подхода:
1) Использование только одного запроса для получения полного списка партий для списания для всего перечня номенклатуры;
2) Относительная простота применяемого запроса для понимания;
3) Применение функций языка запросов для ускорения обработки вместо прямого перебора в коде;
4) Возможность дальнейшей оптимизации использования данного запроса;
45. anig99 2843 25.08.11 14:51 Сейчас в теме
(43) вот бы если полный код процедуры списания партий на замену штатному...и замеры производительности на больших объемах.
47. y-str 60 25.08.11 15:06 Сейчас в теме
(45)(46) Насчет "полный код процедуры списания на замену штатному":
1) Выполняем запрос, получаем все реквизиты для формирования движений списания (период, вид движений, номенклатура, партия, количество, сумма);
2) Загружаем в реквизит объекта документа "Движения" результат выполнения запроса;
3) Записываем "Движения";

Провести полноценный тест запроса не имею возможности. Но чисто теоретически он должен выполнятся крайне быстро и эффективно. Я верю в него :)
48. anig99 2843 25.08.11 15:15 Сейчас в теме
(47)
1) для одного документа или всех сразу?

на одном документе разница будет незаметна, т.к. больше времени уходит на запись, а не чтение.
50. y-str 60 25.08.11 15:23 Сейчас в теме
(48) Можно сделать и для всех документов сразу: в качестве "таблицы ограничений" для моего запроса можно использовать таблицу с полями "регистратор + номенклатура + количество списания" и в самом запросе просто добавить еще одну группировку по регистратору. Вот и все :)
49. y-str 60 25.08.11 15:20 Сейчас в теме
(44)На мой взгляд приведенный "запрос в лоб на мисте" выглядит неоптимальным: применяется вложенный запрос по периодом (получается список неповторяющихся периодов), потом соединяется с полным списком периодов (не уникальный список периодов), а потом еще и группируется вновь по периодам, подсчитывая сумму.

Более логичным было бы использование такого запроса:

SELECT
tab1.Период КАК Время,
SUM( tab2.СуммаОборот ) КАК Сумма
FROM РегистрНакопления.ПродажиПоДисконтнымКартам.Обороты(, , Регистратор, ДисконтнаяКарта = &Ссылка) AS tab1
LEFT JOIN РегистрНакопления.ПродажиПоДисконтнымКартам.Обороты(, , Регистратор, ДисконтнаяКарта = &Ссылка) AS tab2
ON tab1.Период >= tab2.Период
GROUP BY tab1.Период
51. anig99 2843 25.08.11 15:39 Сейчас в теме
(49) это просто подход к проблеме - простое соединение по условию ">="

и вообще вложенные запросы признаны самой 1с неэффективными. Нужно использовать пакетные запросы. Кстати, формально, те 7 запросов, объединенные в качестве пакетных, являются 1 запросом.
52. y-str 60 25.08.11 15:52 Сейчас в теме
(51) На мисте используется точно такое же соединение по условию ">=" :) В моем варианте запроса исправлены недостатки запроса с мисты.
Еще раз по запросу на мисте:
1) В первом вложенном запросе выбирается список уникальных периодов;
2) Затем во втором вложенном запросе выбирается полный список периодов () вместе с их суммами оборотов;
3) Затем эти два подзапроса соединяются: получается что весь список уникальных периодов соединяется со списком неуникальных периодов;
4) Затем происходит группировка по периодом, то есть опять происходит процедура формирования списка уникальных периодов;

Очевидно, что запрос на мисте не оптимален.

Насчет "7 запросов, объединенных в качестве пакетных": у меня запрос только один :) Судя по текстовому алгоритму из упоминаемой статьи этот алгоритм может быть разбит МИНИМУМ на 3 подзапроса. Еще раз - у меня эта задача решена в один запрос, понятный и ясный для понимания.
53. y-str 60 25.08.11 16:14 Сейчас в теме
(51) А вообще-то мой запрос еще можно оптимизировать: если "РегистрНакопления.ПродажиПоДисконтнымКартам" является только оборотным регистром, то можно вместо виртуальной таблицы оборотов и детализации периодов до регистратора использовать просто полный список движений по регистру. Получилось бы еще быстрее и понятнее.

Вот как-то так:

SELECT
tab1.Период КАК Время,
SUM( tab2.СуммаОборот ) КАК Сумма
FROM РегистрНакопления.ПродажиПоДисконтнымКартам AS tab1
LEFT JOIN РегистрНакопления.ПродажиПоДисконтнымКартам AS tab2
ON tab1.Период >= tab2.Период
WHERE (tab1.ДисконтнаяКарта = &Ссылка) AND (tab2.ДисконтнаяКарта = &Ссылка)
GROUP BY tab1.Период
46. alexk-is 6533 25.08.11 14:58 Сейчас в теме
+45 ...по всем документам движения за месяц. :)
54. ildarovich 7850 25.08.11 16:19 Сейчас в теме
Если автор более точно сформулирует решаемую им задачу, станет понятно, что утверждение
Фактически в данной статье рассматриваются альтернативы запросам, приведенным в статьях http://infostart.ru/public/61295/ и http://infostart.ru/public/68225/.

ошибочно.
Как я понял, автор предлагает вместо получения запросом таблицы партий из регистра накопления "остатки партий товаров" и последующего построения в цикле таблицы списания партий, решать задачу в запросе. Не вижу в этом проблемы. Думаю, что в большинстве решений, поддерживающих партионный учет, так и сделано.
Чаще всего таблице ненулевых остатков партий (по одной номенклатуре) - одна - две строки, что там оптимизировать?
55. y-str 60 25.08.11 16:23 Сейчас в теме
(54) В моей статье в качестве последнего запроса приведено прямое решение для задачи из http://infostart.ru/public/61295/. Приведенное мною решение более компактно и понятно. Использования запросов такого вида где-либо еще (в типов ли конфигурациях или просто на просторах Интернета) я не нашел - буду благодарен за любую ссылку на подобный материал!
56. Ish_2 1104 25.08.11 17:02 Сейчас в теме
(55) Вышел с "больничного".
Реализация метода ФИФО предполагает получение движений для всех документов расхода за период.
Именно в такой постановке рещается задача в "ФИФо для любопытных".

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

На практике при реализации метода ФИФО на входе имеем не таблицу с итогами количества по списанию ,
а таблицу с колонками
• Столбец «ДокументРасходнаяНакладная»;
• Столбец «Номенклатура»;
• Столбец «Количество» - количество списания по накладной

А это значит на выходе мы должны получить НЕ Вашу таблицу с колонками :
• Столбец «Номенклатура»;
• Столбец «Партия»;
• Столбец «КоличествоСписания» - количество списания по накладной
• Столбец «СуммаСписания» - количество списания по накладной

А другую таблицу
Столбец «ДокументРасходнаяНакладная»;
• Столбец «Номенклатура»;
• Столбец «Партия»;
• Столбец «КоличествоСписания» - количество списания по накладной
• Столбец «СуммаСписания» - количество списания по накладной
57. y-str 60 25.08.11 17:09 Сейчас в теме
(55) Вспомнилась фраза из старого фильма, сказанная со смешной интонацией - "Не вижу препятствий!" :) Этот вопрос я уже обсуждал в (50): очень просто вместо таблицы только с номенклатурой и количеством получить таблицу с документом, всей номенклатурой и всеми количествами. Точно также используем ее в запроса, добавляя только группировку по регистратору. То есть в "ТаблицеНоменклатуры" будет еще одно поле - "РасходнаяНакладная" (или лучше назвать это поле сразу "Регистратор" для последующей выгрузки результата запроса в набор записей движений).

Повторюсь - запросы в статье открыты для экспериментов и оптимизаций, все в Ваших руках! :)
58. Ish_2 1104 25.08.11 17:37 Сейчас в теме
(57) Статья была обозначена как альтернатива статье "Фифо для любопытных".
Я из этого и исхожу.
Но Ваша постановка задачи есть частный случай и сильное упрощение постановки задачи в "ФИФО для любопытных".
Т.е. никакая НЕ альтернатива.

С другой стороны , если Вы представите текст запроса для случая , когда на входе
таблица
• Столбец «ДокументРасходнаяНакладная»;
• Столбец «Номенклатура»;
• Столбец «КоличествоСписания»;

нам будет легко сравнивать альтернативные запросы.
И будет о чем поговорить. Пока нечего сравнивать.
59. y-str 60 25.08.11 17:49 Сейчас в теме
(58) Моя статья предназначена для демонстрации другого способа получения списка партий для списания вместе со всеми количествами/суммами. Демонстрация превосходств того или иного метода - тема для отдельного исследования и статьи :) Возможно я этим и займусь, но позже.
Но все, что нужно для модификации моего запроса я уже даже описал сам :)
60. Ish_2 1104 25.08.11 18:01 Сейчас в теме
(59) Жаль.
1. При решении задачи полноценного ФИФО , т.е. получения движений для каждого документа расхода Вас ждут сюрпризы. И описанной Вами модификацией - лишь "добавляя только группировку по регистратору" - Вы ничего не добьетесь.
2. Остался без проверки главный подводный камень, на который налетают при использовании соединения по неравенству. При приличных объемах входных данных Ваш алгоритм - "рухнет".
См. Пример с таблицей 1 000 000 записей, которая соединяется сама с собой по неравенству.

Если бы было найдено решение , учитывающее 1 и 2 и которое принципиально отличалось бы от уже опубликованных на ИС - тогда бы мы поговорили всерьез.
61. y-str 60 25.08.11 18:10 Сейчас в теме
(60) Обещаю, что написание полноценного запроса под "полноценное ФИФО" будет темой моей следующей статьи :)
62. Ish_2 1104 25.08.11 18:11 Сейчас в теме
78. y-str 60 30.09.11 18:58 Сейчас в теме
(62)Написал статью, как и обещал. Но в итоге получилось две: Вычисление нарастающего итога для N таблиц в рамках одного запроса и Получение реквизитов движений для множества документов в рамках одного запроса.
В понедельник с утра опубликую их и здесь - хотелось бы привлечь к статьям больше внимания и конструктивной критики. Пока можно попытаться обсудить статьи здесь :)
80. anig99 2843 30.09.11 20:52 Сейчас в теме
(78) обязательно нужно указать в статье, что запросы эти ресурсоёмкие, у чем больше записей в начальный таблицах, тем дольше он будет выполняться - по нарастающей. Я не привык читать сложные запросы из текста, но постараюсь разобраться в них.
81. y-str 60 30.09.11 21:40 Сейчас в теме
(80) anig99, насчет "ресурсоемкости" - проверки на эту характеристику для моих запросов у меня отсутствуют. Если кто-то смог бы их проверить на больших объемах данных (с выкладыванием статистики) то я был бы очень благодарен.
82. anig99 2843 30.09.11 22:25 Сейчас в теме
(81) насчет статистики не могу помочь пока. Но запрос с нарастающими итогами по взаиморасчетам за 3 года выполнялся около 30 минут. Просто логически рассуди - к каждой записи присоединяются все предыдущие и конечная таблица перед группировкой возрастает многократно. Представь 10 записей в начальной - это 1 + (1+1) + (1 + 1 + 1) + (1 + 1 + 1 + 1). Формула f(n) = (n² + n) / 2. 10 объединяемых записей выльется в 55 записей, которые нужно сгруппировать, 100 в 5050

График.
Прикрепленные файлы:
83. y-str 60 01.10.11 10:44 Сейчас в теме
(82) anig99, то, что я привел в статьях это вычисление нарастающего итога с одновременным применением больших ограничений на размер выборки. Так что однозначно говорить о "ресурсоемкости" приведенных мною запросов нельзя, по-крайней мере нельзя без предварительных практических экспериментов.
84. anig99 2843 01.10.11 12:05 Сейчас в теме
(83) даже жесткие ограничения на выборку могут не помочь - слишком быстро растёт количество объединяемых записей. Попробую получше посмотреть запросы и определить гарантируют ли ограничения оптимизацию выполнения.
85. Ish_2 1104 01.10.11 15:04 Сейчас в теме
(82) Кхы.. кхы..
Сумму членов арифметической прогресии находил когда -то маленький Гаусс на уроке:
(А1+АN)*N/2
Если в начальной таблице 100 записей, то при соединении каждой записи со всеми предыдущими получаем :
А1=1,АN=100,N=100.
(1+100)*100/2 = 5050
Итак ,При соединении каждой записи со всеми предыдущими получаем получаем в итоговой таблице 5050 записей.
Промежуточная таблица возросла в 55 раз.
(83) Игнорировать такое возрастание невозможно. Любые алгоритмы , игнорирующие это обстоятельство нельзя рассматривать всерьез.
86. y-str 60 01.10.11 15:34 Сейчас в теме
(85) Ish_2, я придерживаюсь общепринятой позиции, что любая теория подлежит проверке на практике.
87. anig99 2843 01.10.11 19:12 Сейчас в теме
(86) даже, что при достаточном количестве взрывов водородных бомб возможен запуск цепной реакции термоядерного синтеза тяжелой воды в мировом океане?
88. y-str 60 01.10.11 20:12 Сейчас в теме
(87) anig99, как-раз сейчас ищу "достаточное количество водородных бомб" для данного эксперимента :)
89. Ish_2 1104 01.10.11 21:55 Сейчас в теме
(86) Я к эксперименту и призываю . Месяц назад в (7) был предлжено :
Можно убедиться в этом самостятельно : создайте таблицу tab1 с количеством записей 1 000 000 .
Запустите Ваш запрос - соединение по неравенству tab1 "сама с собой" засеките время. И всё поймете... назавтра.


Попробуете ?
90. y-str 60 01.10.11 22:00 Сейчас в теме
(89) Ish_2, месяц назад я написал пост (69).
92. alexk-is 6533 01.10.11 22:33 Сейчас в теме
(90) Могу что-нибудь потестировать. :)
Есть все версии платформы и почти все типовые конфигурации фирмы 1С.
Могу развернуть как файловые, так и SQL базы данных (кроме Oracle).
93. y-str 60 01.10.11 22:36 Сейчас в теме
(92) alexk-is, супер! К статье Получение реквизитов движений для множества документов в рамках одного запроса прикреплена конфигурация. Там все очень "заточено" под одну задачу, но тем не менее данная конфигурация подходит для тестирования. Если у Вас получиться прогнать на ней нагрузочное тестирования и представить результаты я буду очень благодарен.
94. alexk-is 6533 01.10.11 23:25 Сейчас в теме
(93) Скачал. Установил. Как её подготовить к нагрузочным тестам? И где эти тесты?
Вообще-то я расчитывал на что-то вроде этого http://forum.infostart.ru/forum26/topic41810/message451107/#message451107
В плане того, что мне останется только понажимать кнопочки и опубликовать результаты. А тут получается, что нужно и данные набить, и методику нагрузочного тестирования придумать?
95. y-str 60 02.10.11 08:27 Сейчас в теме
(94) alexk-is, хорошо, я приготовлю как специализированную конфигурацию, так и все остальные обработки. На следующей неделе постараюсь сделать и известить Вас.
96. alexk-is 6533 02.10.11 08:52 Сейчас в теме
(95) Возможно, что специализорованная конфигурация и не нужна вовсе. Нужны обработки для заполнения базы данных и обработки для тестирования. Конфигурацию для тестирования можно взять любую. Даже ту, что уже есть.
97. y-str 60 02.10.11 10:31 Сейчас в теме
(96) alexk-is, на самом деле я решил провести тестирование сам на SQL Server 2008R2: сделаю имитацию таблиц партий и документов, затем заполню необходимым количеством данных и запущу запрос. Заодно нормально просмотрю план выполнения запроса.
98. Ish_2 1104 02.10.11 17:48 Сейчас в теме
(96) Ставлю на тебя - 1 $m. Смотри не подведи.
99. alexk-is 6533 02.10.11 19:50 Сейчас в теме
(98) Вообще-то я предлагал помощь, а не соревнование...
100. y-str 60 02.10.11 23:07 Сейчас в теме
(99) alexk-is, кстати еще раз спасибо за предложение помощи! Я это высоко оценил.
91. alexk-is 6533 01.10.11 22:25 Сейчас в теме
(78) Про счетчики прикольно.
79. y-str 60 30.09.11 19:38 Сейчас в теме
(62) Ish_2, мой предыдущий пост для Вас :)
66. y-str 60 25.08.11 18:44 Сейчас в теме
(60) Насчет "алгоритм рухнет". На самом деле "сравнение по неравенству" применяется в базах повсеместно. Прежде всего при сортировке строк - ведь всем известно, что любые алгоритмы сортировки используют "сравнение по неравенству", иначе отсортировать строки невозможно. Естественно, что для эффективной сортировки необходимо чтобы на сортируемых столбцах стоял уникальный индекс. Сортировка будет работать и без него, вот только в этом случае конечно "алгоритм рухнет" - будет выполнятся ооочень долго и с огромными затратами памяти. Но все в наших руках, и установить индекс по измерению регистра мы можем. Так что все впорядке :)
68. Ish_2 1104 25.08.11 18:53 Сейчас в теме
(66) Разумеется , предварительно для таблицы, которая соединятся сама с собой , создается индекс по полю соединения. Лишь после получения индекса мы запускаем соединение "сама с собой" и засекаем время (таблица
имеет 1 000 000 записей).
..Дольше мне писать , чем Вам попробовать.
69. y-str 60 25.08.11 19:00 Сейчас в теме
(68) Дык вот попробывать то нет возможности, я бы с радостью - у меня только "Версия для обучения программированию" со встроенным 1С ограничением размера таблиц :) Как только найду нормальную систему - обязательно попробую!
70. alexk-is 6533 25.08.11 20:40 Сейчас в теме
(69) Так с этого и нужно было начинать... :)
73. y-str 60 25.08.11 22:13 Сейчас в теме
(70) На контекст моей статьи из-за версии программного обеспечения влияния нет.
63. ildarovich 7850 25.08.11 18:21 Сейчас в теме
(55)
приведено прямое решение для задачи из http://infostart.ru/public/61295/

- опять ошибаетесь!
Вы решаете другую задачу.
Вы считаете известной на ткущий момент ТаблицуДолгов с колонками: Контрагент, Накладная, СуммаДолга.
Чтобы ее получить, нужно один за другим последовательно провести документы по регистру взаиморасчетов по документам расчетов.
В решении http://infostart.ru/public/61295/ этого не требуется.
То есть оно работает при отсутствии в конфигурациях регистра взаиморасчетов по документам расчетов.
Как, кстати и не требуется перепроведения при изменении документов задним числом.
Другая задача - другие методы, как можно сравнивать?
Вы привели очевидное решение своей задачи.
Очевидное потому, что по-другому запрос и не записать, поставив задачу получить запросом списываемые партии из регистра партий.
И если бы не заблуждения относительно того, что это решение чего-то проще и компактней, то статья вполне может здесь пригодиться.
64. y-str 60 25.08.11 18:26 Сейчас в теме
(63) Я вот цитату приведу из http://infostart.ru/public/61295/:
Постановка задачи.

Даны две таблицы:
Таблица «Долги» ...


Я что-то путаю? Решаю другую задачу? Или привожу давно всем известное и избитое решение? Буду благодарен за любые ссылки на "аналоги" :)
65. ildarovich 7850 25.08.11 18:42 Сейчас в теме
(64) Именно так! - Путаете! В http://infostart.ru/public/61295/ в таблице долги нет колонки "Накладная".
Там для одного контрагента - одна строка: Сумма долга (текущая) и дата отсрочки.

Не знаю, насколько кому это решение известное.
Оно очевидное.
Потому что любой опытный программист напишет такое же.
Труднее написать по-другому.
Ну а очевидность для публикации здесь не препятствие.
67. y-str 60 25.08.11 18:48 Сейчас в теме
(65) Ах, теперь мы уже говорим про таблицу "ТаблицаОборотов"? :) В ней накладная в первичной статье есть, ищите.

А выпады вроде "да это все фигня, любой так бы написал" - это уже без обсуждений :)
76. ildarovich 7850 25.08.11 23:34 Сейчас в теме
(54) (63) (65) - в этих комментариях я ошибся в части задачи задолженности :cry: : задача о просроченной задолженности одна и та же!

Тем не менее, когда документов по одному контрагенту станет достаточно много,
приведенный запрос будет работать слишком долго - зависимость от числа документов квадратичная (показано в комментарии (18)).
А ведь срок давности документов в запросе не ограничен.

А вот запрос для списания партий вполне рабочий: ведь не списанных партий обычно немного (чаще даже одна).

(71) внимания, как я уже говорил, статья достойна.

Цель моих комментариев - исправить замеченные неточности относительно "альтернативности" подхода.

То есть в итоге мои выводы таковы:
1. для просроченных долгов запрос в приведенном виде не годится. Это не альтернатива.
2. для списания партий в самописных конфигурациях, если считать, что решается другая и даже более распространенная задача, вполне подходит.

Мог бы изложить свое понимание того, почему в типовых используется предварительная выгрузка остатков в таблицу, но не буду отвлекать от темы.

Простоту также считаю большим плюсом.
77. y-str 60 26.08.11 09:39 Сейчас в теме
(76) Приведенный запрос успешно посчитает "просроченные долги" при любом количестве документов. Долго ли, али нет - дело ума того, кто будет применять это на практике :)
Вопросы оптимизации умышленно вынесены за рамки моей статьи в угоду простоте изложения материала и его понятности, о чем и сказано в последнем абзаце текста статьи.
71. ildarovich 7850 25.08.11 21:53 Сейчас в теме
75. y-str 60 25.08.11 22:22 Сейчас в теме
(71) В моей статья я показал другой метод получения списка партий для списания, отличный от всего, что я нашел на просторах Интернета. Он реально работает, он компактен и по своему красив. Среди всего множества людей наверняка есть и такие, кто его уже знают - я это допускаю. Кому-то он поможет, кому-то нет. Но своей цели я уже достиг - несколько человек посчитали статью стоящей и полезной.

Я полностью уверен, что при любых условиях хранения движений (остатков/оборотов), будь то регистр или справочник - этот запрос будет работать. Еще раз - доказывать кому-то что мой запрос лучше или хуже у меня цели нет. Считаете, что моя статья недостойна внимания - я буду работать с другими, которым она полезна.
ildarovich; +1 Ответить
72. Hany 25.08.11 22:12 Сейчас в теме
Я плюсую за простоту кода и его дальнейшую понятность для остальных программистов в случае доработок даже без коммментариев.

Сегодня этот код успешно применен и протестирован на рабочей базе.
Оговорюсь, что вместо виртуальных таблиц Обороты использовала уже заранее сформированные временные таблицы в одном немаленьком запросе (таким образом СКЛю будет несложно выбрать оптимальный план запроса).
Так как запрос изначально был немаленьким, то вставлять в него еще 7 подзапросов считаю перегрузом. А так всего десяток строк - и наглядно и просто. Keep it simple!
P.S. У меня в соединяемых временных таблицах никогда не будет 1 000 000 записей, поэтому не боюсь, что запрос рухнет на огромном массиве данных.

Спасибо автору!
Оставьте свое сообщение