powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / MODEL, ratio_to_report, нужна помощь
9 сообщений из 9, страница 1 из 1
MODEL, ratio_to_report, нужна помощь
    #39304367
Задача:
посчитать перераспределение премии по сотрудникам, так как его никто не считал на каждого, а вносили общую сумму на всех.
Что сделано:
первое поколение считаю так:

Код: plsql
1.
2.
premium_obj [any, any] order by pk /*поколение, высчитывается по дате*/, object /*проект за который платили премию*/ =
premium /*общая премия на дату*/ / count (premium) [cv (), any]



Сама премия распределяется всегда в одинаковых пропорциях на каждого сотрудника, то есть, если из 100 рублей сотрудник получил 10, то из 50 он получит 5, если количество сотрудников не изменилось.
Но при добавлении в проект нового сотрудника, его коэффициент может отличаться от других.
второе и последующие поколения считаю так:

Код: plsql
1.
premium[cv(), cv ()] * premium_obj[cv()-1, cv ()] \ sum (premium_obj)[cv()-1, cv ()]


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

Попытка сделать sum (nvl2 (premium_obj[cv(), cv ()]), premium_obj[cv()-1, cv ()], 0)[cv()-1, cv ()] или как-нибудь так провалилась. Не позволяет модель двойную адресацию делать.

Посчитать ratio_to_report также нет возможности, так как возникает ошибка 30483.

Подскажите пожалуйста, как можно посчитать в модели сумму по прошлому поколению, используя данные из текущего поколения.

Заранее спасибо.
...
Рейтинг: 0 / 0
MODEL, ratio_to_report, нужна помощь
    #39304390
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Постановку задачи по SQL всегда нужно начинать с описания и примера входных данных.
...
Рейтинг: 0 / 0
MODEL, ratio_to_report, нужна помощь
    #39304391
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Перечень печенья в печени,

В дополнение к ответу на вопрос выше еще не мешало бы уточнить откуда навязчивое желание натянуть модель.
...
Рейтинг: 0 / 0
MODEL, ratio_to_report, нужна помощь
    #39304405
Модель натянуть захотелось потому, что LAG\LEAD не справляется, нужен пересчет всех поколений, а их там бывает до 20 по некоторым проектам.

данные

OBJECTDDATEPKPREMIUMPERSON_ID103.09.201662000001103.09.201662000002103.09.201662000003103.09.201662000004103.09.201662000005103.09.201662000006103.09.201662000007103.09.201662000008104.09.2016620000010102.09.201652000001102.09.201652000002102.09.201652000003102.09.201652000004102.09.201652000005102.09.201652000006102.09.201652000007102.09.201652000008102.09.201652000009102.09.2016520000010101.09.201642500001101.09.201642500002101.09.201642500003101.09.201642500004101.09.201642500005101.09.201642500006101.09.201642500007101.09.201642500008101.09.201642500009101.09.2016425000010131.08.201632500001131.08.201632500002131.08.201632500003131.08.201632500004131.08.201632500005131.08.201632500006131.08.201632500007131.08.201632500008131.08.201632500009131.08.2016325000010130.08.201622000001130.08.201622000002130.08.201622000003130.08.201622000004130.08.201622000005130.08.201622000006130.08.201622000007130.08.201622000008130.08.201622000009127.08.201612000001127.08.201612000002127.08.201612000003127.08.201612000004127.08.201612000005127.08.201612000006127.08.201612000007127.08.201612000008127.08.201612000009




В результате надо получить в первом поколенее premium_obj = premium/9.
В третьем надо у первых 9 работников оставать премию как есть, а новому посчитать 50000.
5-е поколение надо расчитать так, чтобы 50000, вычтенных из премии, распределились по объектам, сохраняя при этом коэффициенты.
То есть, должно получиться что-то вроде 17777.(7) у 9 работников и 40000 у оставшегося.
6-е поколение надо рассчитать так, чтобы разница в суммах перераспределилась пропорционально.
И вот этот как раз момент у меня не получается.
...
Рейтинг: 0 / 0
MODEL, ratio_to_report, нужна помощь
    #39304407
Ой...
Даты немного поплыли при запихивании их в таблицу...
...
Рейтинг: 0 / 0
MODEL, ratio_to_report, нужна помощь
    #39304780
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Перечень печенья в печениОй...
Даты немного поплыли при запихивании их в таблицу...Нахрена вообще указывать атрибуты, которые не имеют никакого отношения к задаче?
Лучше б ты привел то, что надо и в формате with.
Код: 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.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
SQL> with t0 (pk,  premium,  person_id) as
  2  (select 6,  200000, 1 from dual
  3  union all select 6,  200000, 10 from dual
  4  union all select 5,  200000, 1 from dual
  5  union all select 5,  200000, 9 from dual
  6  union all select 5,  200000, 10 from dual
  7  union all select 4,  250000, 1 from dual
  8  union all select 4,  250000, 9 from dual
  9  union all select 4,  250000, 10 from dual
 10  union all select 3,  250000, 1 from dual
 11  union all select 3,  250000, 9 from dual
 12  union all select 3,  250000, 10 from dual
 13  union all select 2,  200000, 1 from dual
 14  union all select 2,  200000, 9 from dual
 15  union all select 1,  200000, 1 from dual
 16  union all select 1,  200000, 9 from dual)
 17  , t as
 18  (
 19  select t1.*, t2.person_id p_prev, t3.person_id p_next
 20  from t0 t1
 21  left join t0 t2 on t1.pk - 1 = t2.pk and t1.person_id = t2.person_id
 22  left join t0 t3 on t1.pk + 1 = t3.pk and t1.person_id = t3.person_id
 23  )
 24  select pk, person_id, premium, r, premium * r x
 25  from t
 26  model
 27  dimension by (pk, person_id)
 28  measures (premium, 0 r, p_prev, p_next)
 29  rules
 30  (
 31    r[any, any] order by pk, person_id =
 32    case
 33    -- first iteration
 34    when cv(pk) = 1 then 1/count(premium)[cv(pk), any]
 35    else
 36      case
 37      -- added person(s)
 38      when count(*)[cv(pk), any] > count(*)[cv(pk)-1, any]
 39      then nvl(-- ratio for existing person(s)
 40               r[cv(pk)-1, cv(person_id)]*premium[cv(pk)-1, cv(person_id)]/premium[cv(pk), cv(person_id)],
 41               -- ratio for new person(s)
 42               (premium[cv(pk), cv(person_id)] - max(premium)[cv(pk)-1, any])/premium[cv(pk), cv(person_id)]/count(nvl2(p_prev,null,1))[cv(pk), any])
 43      -- removed person(s)
 44      when count(*)[cv(pk), any] < count(*)[cv(pk)-1, any]
 45      then r[cv(pk)-1, cv(person_id)]/sum(r*nvl2(p_next,1,null))[cv(pk)-1, any]
 46      -- the same
 47      else r[cv(pk)-1, cv(person_id)]
 48      end
 49    end
 50  )
 51  order by pk desc, person_id;

        PK  PERSON_ID    PREMIUM          R          X
---------- ---------- ---------- ---------- ----------
         6          1     200000 .666666667 133333.333
         6         10     200000 .333333333 66666.6667
         5          1     200000         .4      80000
         5          9     200000         .4      80000
         5         10     200000         .2      40000
         4          1     250000         .4     100000
         4          9     250000         .4     100000
         4         10     250000         .2      50000
         3          1     250000         .4     100000
         3          9     250000         .4     100000
         3         10     250000         .2      50000
         2          1     200000         .5     100000
         2          9     200000         .5     100000
         1          1     200000         .5     100000
         1          9     200000         .5     100000

15 rows selected.



Интересно было бы попробовать решить с помощью recursive subquery factoring, хотя есть подозрение, что из-за множества ограничений на рекурсивный член, не взлетит.
...
Рейтинг: 0 / 0
MODEL, ratio_to_report, нужна помощь
    #39304784
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshopИнтересно было бы попробовать решить с помощью recursive subquery factoring, хотя есть подозрение, что из-за множества ограничений на рекурсивный член, не взлетит.Взлетело.
Код: 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.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
SQL> with t0 (pk,  premium,  person_id) as
  2  (select 6,  200000, 1 from dual
  3  union all select 6,  200000, 10 from dual
  4  union all select 5,  200000, 1 from dual
  5  union all select 5,  200000, 9 from dual
  6  union all select 5,  200000, 10 from dual
  7  union all select 4,  250000, 1 from dual
  8  union all select 4,  250000, 9 from dual
  9  union all select 4,  250000, 10 from dual
 10  union all select 3,  250000, 1 from dual
 11  union all select 3,  250000, 9 from dual
 12  union all select 3,  250000, 10 from dual
 13  union all select 2,  200000, 1 from dual
 14  union all select 2,  200000, 9 from dual
 15  union all select 1,  200000, 1 from dual
 16  union all select 1,  200000, 9 from dual)
 17  , t as
 18  (
 19  select t1.*, sign(t0.pk) actual
 20    from t0
 21   right join (select pk, person_id, premium
 22                 from (select distinct person_id from t0),
 23                      (select distinct pk, premium from t0)) t1
 24      on t0.person_id = t1.person_id
 25     and t0.pk = t1.pk
 26  )
 27  , rec (pk, person_id, premium, actual, cnt, r) as
 28  (
 29  select t.pk, t.person_id, t.premium, t.actual, count(t.actual) over (), 1/count(actual) over () r
 30    from t where pk = 1
 31  union all
 32  select t.pk, t.person_id, t.premium, t.actual, count(t.actual) over (),
 33         case
 34         when count(t.actual) over () > rec.cnt
 35         then decode(rec.actual,1,rec.r*rec.premium/t.premium,(t.premium-rec.premium)/t.premium/(count(t.actual) over ()-rec.cnt))
 36         when count(t.actual) over () < rec.cnt
 37         then rec.r/sum(rec.r*t.actual) over ()
 38         else rec.r
 39         end
 40    from t, rec where t.pk = rec.pk + 1 and t.person_id = rec.person_id
 41  )
 42  select pk, person_id, premium, r, premium * r x
 43    from rec
 44   where actual = 1
 45  order by pk desc, person_id;

        PK  PERSON_ID    PREMIUM          R          X
---------- ---------- ---------- ---------- ----------
         6          1     200000 .666666667 133333.333
         6         10     200000 .333333333 66666.6667
         5          1     200000         .4      80000
         5          9     200000         .4      80000
         5         10     200000         .2      40000
         4          1     250000         .4     100000
         4          9     250000         .4     100000
         4         10     250000         .2      50000
         3          1     250000         .4     100000
         3          9     250000         .4     100000
         3         10     250000         .2      50000
         2          1     200000         .5     100000
         2          9     200000         .5     100000
         1          1     200000         .5     100000
         1          9     200000         .5     100000

15 rows selected.



В обоих решениях предполагается, что на конкретной итерации не могут одновременно добавляться и удаляться persons.
...
Рейтинг: 0 / 0
MODEL, ratio_to_report, нужна помощь
    #39305385
Спасибо большое за ответы.
Кажется, получилось оба варианта прикрутить, правда, немного допилить пришлось.
Успехов вам и хорошего вечера (если у вас вечер).
...
Рейтинг: 0 / 0
MODEL, ratio_to_report, нужна помощь
    #39306228
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Перечень печенья в печени,

Во втором случае вместо лишнего соединения в t просится join partition by pk, premium.
Для тюнинга, имело бы смысл аналитику (count) предварительно посчитать и, возможно, использовать временную таблицу с индексом по pk если много данных и высокая кардинальность по pk.
Модель тоже можно несколько улучшить, но оба решения сильно уступают PL/SQL как по производительности так и по масштабируемости. Разве что текста меньше.
Так что запросы были опубликованы больше для демонстрации возможностей инструмента.
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / MODEL, ratio_to_report, нужна помощь
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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