powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Задача на аллокацию кредитов по залогам с помощью аналитических функций
11 сообщений из 11, страница 1 из 1
Задача на аллокацию кредитов по залогам с помощью аналитических функций
    #39703147
hardwinter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте!

Прошу помощи в написании запроса с помощью аналитических функций (без рекурсии). Как сделать решение с помошью рекурсии, представляю, поэтому интереса в таком решении нет.

Задача представляет собой аллокацию кредитов по залогам.
Есть кредиты, которые обеспечиваются залогами. Один залог может обеспечивать несколько кредитов, так и кредит может обеспечиваться несколькими залогами. Задача состоит в том, чтобы разложить кредиты по залогам в определенном порядке, заданной в таблице allocation полем priority.

Задача очень похожа на Укомплектование заказов товарами с полок склада , но с некоторым отличием, есть порядок распределения. Из-за этой особенности алгоритм раскладывания, предложенный в той теме, не работает.

Данные:
Код: 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.
--Залоги
create table pledges(id number,value number);
insert numbero pledges values(1,100);
insert numbero pledges values(2,170);
insert numbero pledges values(3,70);

-- Кредиты
create table loans(id number,value number);
insert numbero loans values(1,50);
insert numbero loans values(2,80);
insert numbero loans values(3,60);
insert numbero loans values(4,90);
insert numbero loans values(5,90);

-- Порядок аллокации
create table allocation(id_pledge number,id_loan number,priority number);
insert numbero allocation values(1,1,1);
insert numbero allocation values(1,2,2);
insert numbero allocation values(1,3,3);
insert numbero allocation values(2,4,4);
insert numbero allocation values(2,3,5);
insert numbero allocation values(2,2,6);
insert numbero allocation values(3,5,7);
insert numbero allocation values(3,2,8);



Вот, что необходимо получить:

id_pledgepledge_valueid_loanloan_valuepriorityallocatednot_allocated1100150150011002802503011003603060217049049002170360560021702806200370590770203702808010

Возможно ли вообще решить эту задачу обычным запросом без рекурсии и без процедурного языка?
...
Рейтинг: 0 / 0
Задача на аллокацию кредитов по залогам с помощью аналитических функций
    #39703148
hardwinter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Извиняюсь, в данных ошибка синтаксическая. Исправил.
Данные:
Код: 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.
--Залоги
create table pledges(id number,value number);
insert into pledges values(1,100);
insert into pledges values(2,170);
insert into pledges values(3,70);

-- Кредиты
create table loans(id number,value number);
insert into loans values(1,50);
insert into loans values(2,80);
insert into loans values(3,60);
insert into loans values(4,90);
insert into loans values(5,90);

-- Порядок аллокации
create table allocation(id_pledge number,id_loan number,priority number);
insert into allocation values(1,1,1);
insert into allocation values(1,2,2);
insert into allocation values(1,3,3);
insert into allocation values(2,4,4);
insert into allocation values(2,3,5);
insert into allocation values(2,2,6);
insert into allocation values(3,5,7);
insert into allocation values(3,2,8);
...
Рейтинг: 0 / 0
Задача на аллокацию кредитов по залогам с помощью аналитических функций
    #39703311
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hardwinterКак сделать решение с помошью рекурсии, представляю, поэтому интереса в таком решении нет.Не стесняйся, демонстрируй.
hardwinterадача состоит в том, чтобы разложить кредиты по залогам в определенном порядке, заданной в таблице allocation полем priority.Так они уже разложены. Пусть тот шибко умный манагер, предложивший такое распределение, сразу укажет и суммы в качестве доказательства его сходимости.
...
Рейтинг: 0 / 0
Задача на аллокацию кредитов по залогам с помощью аналитических функций
    #39703778
j2k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hardwinter, какая версия oracle?
...
Рейтинг: 0 / 0
Задача на аллокацию кредитов по залогам с помощью аналитических функций
    #39703792
j2k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hardwinter, и непонятно, как в строке с priority 6 и 8 получились такие значения столбца not_allocated. Или там опечатка и должны были быть значения 60 и 80 ?
...
Рейтинг: 0 / 0
Задача на аллокацию кредитов по залогам с помощью аналитических функций
    #39703872
hardwinter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
j2khardwinter, и непонятно, как в строке с priority 6 и 8 получились такие значения столбца not_allocated. Или там опечатка и должны были быть значения 60 и 80 ?
Да, Вы правы, есть ошибка. Исправил.

Вот, что необходимо получить:
id_pledgepledge_valueid_loanloan_valuepriorityallocatednot_allocated11001501500110028025030110036030602170490490021703605600217028062010370590770203702808010

Кредиту под номером 2 так и не достанется 10 условных единиц залога.

Версия Oracle 12c.
...
Рейтинг: 0 / 0
Задача на аллокацию кредитов по залогам с помощью аналитических функций
    #39703908
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hardwinterВозможно ли вообще решить эту задачу обычным запросом без рекурсии и без процедурного языка?Решается моделью, но не особо эффективно. Если записей тысячи, а не миллионы, то не критично.

Я практически идентичную задачу описывал в книге под названием Baskets (см. содержание).

Аналитикой нерешаемо ибо невозможно учесть какая часть уже была аллоцирована.
Нижеследующее может создавать впечатление правильного результата, но это только магия данных.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
SQL> select p.*,
  2         a.*,
  3         l.*,
  4         greatest(least(l.value + p.value - sum(l.value) over(partition by p.id order by a.priority), l.value), 0) allocated
  5    from pledges p
  6    join allocation a
  7      on a.id_pledge = p.id
  8    join loans l
  9      on a.id_loan = l.id
 10   order by p.id, a.priority;

        ID      VALUE  ID_PLEDGE    ID_LOAN   PRIORITY         ID      VALUE  ALLOCATED
---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
         1        100          1          1          1          1         50         50
         1        100          1          2          2          2         80         50
         1        100          1          3          3          3         60          0
         2        170          2          4          4          4         90         90
         2        170          2          3          5          3         60         60
         2        170          2          2          6          2         80         20
         3         70          3          5          7          5         90         70
         3         70          3          2          8          2         80          0

8 rows selected.


Здесь полагается что loans are fully reusable across pledges which is no true.
...
Рейтинг: 0 / 0
Задача на аллокацию кредитов по залогам с помощью аналитических функций
    #39704080
j2k
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: 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.
with pledges as(select 1 id_pledge, 100 pledge_value from dual 
      union all select 2 id_pledge, 170 pledge_value from dual
      union all select 3 id_pledge, 70 pledge_value from dual
   )
   , loans as (select 1 id_loan, 50 loan_value from dual 
     union all select 2 id_loan, 80 loan_value from dual
     union all select 3 id_loan, 60 loan_value from dual
     union all select 4 id_loan, 90 loan_value from dual
     union all select 5 id_loan, 90 loan_value from dual
   )
   , allocation as (select 1 id_pledge_ref, 1 id_loan_ref, 1 priority from dual 
          union all select 1 id_pledge_ref, 2 id_loan_ref, 2 priority from dual
          union all select 1 id_pledge_ref, 3 id_loan_ref, 3 priority from dual
          union all select 2 id_pledge_ref, 4 id_loan_ref, 4 priority from dual
          union all select 2 id_pledge_ref, 3 id_loan_ref, 5 priority from dual
          union all select 2 id_pledge_ref, 2 id_loan_ref, 6 priority from dual
          union all select 3 id_pledge_ref, 5 id_loan_ref, 7 priority from dual
          union all select 3 id_pledge_ref, 2 id_loan_ref, 8 priority from dual
    )
------
    , alloc as (select p.*, l.*, a.priority
                     , greatest(l.loan_value - greatest(sum(l.loan_value)over(partition by p.id_pledge order by a.priority) - p.pledge_value,0),0)  allocated
                from allocation a
                inner join pledges p on a.id_pledge_ref=p.id_pledge
                inner join loans l on a.id_loan_ref=l.id_loan
     )
select a.*, a.loan_value - sum(a.allocated) over (partition by a.id_loan order by a.priority) not_allocated
from alloc a
order by a.priority


dbms_photoshop, а на каких данных магия перестанет действовать?
...
Рейтинг: 0 / 0
Задача на аллокацию кредитов по залогам с помощью аналитических функций
    #39704238
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
j2kdbms_photoshop, а на каких данных магия перестанет действовать?Я же пояснил ключевой момент дважды и разными словами.
dbms_photoshopАналитикой нерешаемо ибо невозможно учесть какая часть уже была аллоцирована.dbms_photoshopЗдесь полагается что loans are fully reusable across pledges which is not true.
Соотвественно если добавить, например, такое правило
Код: plsql
1.
insert into allocation values(2,1,3.5);

то 50 будет выделено для второго поручительства хотя оно уже было выделено для первого.
...
Рейтинг: 0 / 0
Задача на аллокацию кредитов по залогам с помощью аналитических функций
    #39706656
hardwinter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
dbms_photoshop, спасибо за развернутый ответ. Вы подтвердили мои предположения, что эта задача в общем случае не решается аналитическими функциями. Посмотрел Вашу книгу, задача Baskets и правда похожа с этой. Также много интересного нашел для себя: хорошо разобранные задачи, описание различных методов решения задач на Oracle.

Я привел, конечно, не лучший пример исходных данных, но в общем случае не все так тривиально. Ниже при решении задачи использовал более сложный пример исходных данных.

Решил эту задачу с помощью Model, чтобы изучить новый для себя инструмент Oracle.

Код: 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.
44.
45.
46.
with pledges as(select 1 id_pledge, 70 pledge_value from dual 
      union all select 2 id_pledge, 160 pledge_value from dual
      union all select 3 id_pledge, 70 pledge_value from dual
   )
   , loans as (select 1 id_loan, 40 loan_value from dual 
     union all select 2 id_loan, 50 loan_value from dual
     union all select 3 id_loan, 80 loan_value from dual
     union all select 4 id_loan, 90 loan_value from dual
     union all select 5 id_loan, 60 loan_value from dual
   )
   , allocation as (select 1 id_pledge_ref, 1 id_loan_ref, 1 priority from dual 
          union all select 1 id_pledge_ref, 2 id_loan_ref, 2 priority from dual
          union all select 1 id_pledge_ref, 3 id_loan_ref, 3 priority from dual
          union all select 2 id_pledge_ref, 1 id_loan_ref, 4 priority from dual
          union all select 2 id_pledge_ref, 2 id_loan_ref, 5 priority from dual
          union all select 2 id_pledge_ref, 4 id_loan_ref, 6 priority from dual
          union all select 2 id_pledge_ref, 5 id_loan_ref, 7 priority from dual
          union all select 2 id_pledge_ref, 3 id_loan_ref, 8 priority from dual
          union all select 3 id_pledge_ref, 5 id_loan_ref, 9 priority from dual
          union all select 3 id_pledge_ref, 3 id_loan_ref, 10 priority from dual
    )
    , alloc as (select p.id_pledge, p.pledge_value, l.id_loan, l.loan_value, a.priority
                from allocation a
                inner join pledges p on a.id_pledge_ref=p.id_pledge
                inner join loans l on a.id_loan_ref=l.id_loan
     )
     
select * 
from alloc
model
dimension by (priority, id_pledge, id_loan)
measures ( pledge_value, loan_value, 0 allocated , 0 not_allocated)
rules
(
    allocated[any,any,any] order by priority, id_pledge, id_loan = least(
	pledge_value[cv(priority), cv(id_pledge), cv(id_loan)] 
                    - nvl(sum(allocated)[priority < cv(priority), cv(id_pledge), any], 0)
	, loan_value[cv(priority), cv(id_pledge), cv(id_loan)] 
                    - nvl(sum(allocated)[priority < cv(priority), any, cv(id_loan)], 0)
            ),

    not_allocated[any,any,any] order by priority, id_pledge, id_loan = 
          loan_value[cv(priority), cv(id_pledge), cv(id_loan)] 
                    - nvl(sum(allocated)[priority <= cv(priority), any, cv(id_loan)], 0)
)
order by priority



Итоговый результат:
PRIORITYID_PLEDGEID_LOANPLEDGE_VALUELOAN_VALUE ALLOCATEDNOT_ALLOCATED111704040021270503020313708008042116040005221605020062416090900725160605010823160800809357060100103370806020
...
Рейтинг: 0 / 0
Задача на аллокацию кредитов по залогам с помощью аналитических функций
    #39706739
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hardwinter,

Спасибо за лестный отзыв. :))
Для полноты картины, not_allocated можно посчитать аналитикой, если allocated уже посчитано моделью
Код: plaintext
loan_value - sum(allocated) over (partition by id_loan order by priority) not_allocated
, но в этом нет никакой выгоды.
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Задача на аллокацию кредитов по залогам с помощью аналитических функций
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]