|
|
|
Рекурсивное распределение суммы по чеку
|
|||
|---|---|---|---|
|
#18+
Добрый день. Есть выборка товаров с заданным порядком и общая сумма скидки, которую необходимо распределить по товарам в заданном порядке. - ITEM_NUM - порядковый номер товара - CODE - код товара - AMOUNT - цена товара Алгоритм распределения следующий. авторСумма скидки текущего товара DISCOUNT_AMOUNT = FLOOR( AMOUNT / "Стоимость нераспределённых товаров" * "Сумма скидки за вычетом уже распределённых товаров") Получается, что величины "Стоимость нераспределённых товаров" и "Сумма скидки за вычетом уже распределённых товаров" по мере обхода товаров уменьшаются (рекурсивно). Пример Код: plsql 1. 2. 3. 4. 5. 6. ITEM_NUMCODEAMOUNT1PRD_1102PRD_21003PRD_3200 Сумма скидки = 309. Работа алгоритма при обходе товаров. 1. ITEM_NUM = 1 DISCOUNT_AMOUNT = FLOOR( 10 / (10+100+200) * 309 ) = 9 2. ITEM_NUM = 2 DISCOUNT_AMOUNT = FLOOR( 100 / (100+200) * (309-9) ) = 100 3. ITEM_NUM = 3 DISCOUNT_AMOUNT = FLOOR( 200 / (200) * (309-9-100) ) = 200 Посмотрел на форуме другие решения похожей задачи. Вариант, когда сумма распределяется по всем товарам с округлением вниз, а остаток - на товар с наибольшей стоимостью, не подходит, т.к. даёт другой результат. Решение на PL/SQL очевидно, ну нужна именно SQL-выборка ввиду специфики доработки. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.11.2016, 07:21 |
|
||
|
Рекурсивное распределение суммы по чеку
|
|||
|---|---|---|---|
|
#18+
PranT, что-то не выходит PranTDISCOUNT_AMOUNT = FLOOR( 100 / (100+200) * (309-9) ) = 100 выходит Код: plsql 1. 99 Может лучше ? Код: plsql 1. а так оба варианта по твоим цифрам Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. по твоей формуле Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.11.2016, 10:19 |
|
||
|
Рекурсивное распределение суммы по чеку
|
|||
|---|---|---|---|
|
#18+
PranTРешение на PL/SQL очевидно, ну нужна именно SQL-выборка ввиду специфики доработки.Можно узнать про "специфику доработки"? Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. От обоих агрегатов в правой части правила можно избавиться, если ввести пару вспомогательных столбцов. Будет больше букв, зато быстрее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.11.2016, 14:07 |
|
||
|
Рекурсивное распределение суммы по чеку
|
|||
|---|---|---|---|
|
#18+
Спасибо, коллеги, за решения. Век живи - век учись. :) Не знал ни о первой возможности (рекурсивные подзапросы), ни об операторе model. Пытался решить задачу через аналитические функции SQL. Буду разбираться и тестировать эти решения на реальных объёмах данных. dbms_photoshopМожно узнать про "специфику доработки"? Процесс ETL, когда требуется обработка большого количества строк из OLTP-системы. Подумалось, что построчная обработка через реализацию алгоритма на PL/SQL будет медленнее, чем использование выборки. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.11.2016, 07:21 |
|
||
|
Рекурсивное распределение суммы по чеку
|
|||
|---|---|---|---|
|
#18+
PranTdbms_photoshopМожно узнать про "специфику доработки"? Процесс ETL, когда требуется обработка большого количества строк из OLTP-системы. Подумалось, что построчная обработка через реализацию алгоритма на PL/SQL будет медленнее, чем использование выборки.Recursive subquery factoring вообще не жилец на больших объемах. Ситуация может быть несколько улучшена, если создать индекс по item_id, тогда в рекурсивном члене будет сканирование по индексу, а не полное сканирование. Производительность model тоже будет все более удручающая, если более 1М строк. Ситуацию несколько может спасти, если можно сделать секционирование модели (partition by) и запустить в parallel. В итоге, pipeline PL/SQL функция (или просто функция, возвращающая коллекцию) выглядит более производительным и сопровождаемым решением. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.11.2016, 14:12 |
|
||
|
Рекурсивное распределение суммы по чеку
|
|||
|---|---|---|---|
|
#18+
PranT, 1. с таким подходом по любому потеряете когда нибудь на округлении и будете бегать кругами и искать почему скидка не равна сумме скидок. 2. чем не устраивает нарастающий итог? 3. не проще ли равновзвешенное распределение с закидыванием остатка на первую или последнюю запись?) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.11.2016, 16:41 |
|
||
|
|

start [/forum/topic.php?fid=52&msg=39351562&tid=1886964]: |
0ms |
get settings: |
11ms |
get forum list: |
16ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
196ms |
get topic data: |
9ms |
get forum data: |
3ms |
get page messages: |
40ms |
get tp. blocked users: |
1ms |
| others: | 290ms |
| total: | 574ms |

| 0 / 0 |
