Нахождение общей суммы вычетов на основе суммы предыдущих строк в SQL - PullRequest
2 голосов
/ 04 октября 2010

У меня довольно сложная проблема, которую я пытался решить в течение последних нескольких дней.В настоящее время я решаю ее с помощью предложения Oracle SQL Model и, возможно, мог бы написать функцию, но я ищу хорошее простое решение с использованием аналитических функций или чего-то еще, но ничего не могу понять.

Для данногополитика (ddpsid), я хочу суммировать столбец вычетов (ddddpc).[Извините за сложные названия столбцов, они не мои].Звучит просто, но если столбец ddbnep имеет значение «Y», то я хочу подвести итог всех предыдущих вычетов и взять текущий вычет как процент от того, что уже было вычтено.Итак, если текущий вычет составляет 10%, а предыдущие вычеты составляют 20% (т. Е. Осталось 80%), то я хочу вычесть 8% (10% или 80%), в общей сложности 28%.

Код ниже - это то, что я сейчас использую:

with my_sample_data as (
  select 1 as ddpsid, ddddsq, ddddpc, ddbnep, ddadep
  from (
    select 1 as ddddsq, 10 as ddddpc, 'N' as ddbnep, 'Y' as ddadep from dual union all
    select 2 as ddddsq, 10 as ddddpc, 'Y' as ddbnep, 'Y' as ddadep from dual union all
    select 3 as ddddsq, 10 as ddddpc, 'N' as ddbnep, 'Y' as ddadep from dual union all
    select 4 as ddddsq, 10 as ddddpc, 'Y' as ddbnep, 'Y' as ddadep from dual
  )
)
--        select
--            ddpsid,
--            cumul as ddddpc
--        from (
          select
            ddpsid,
            ddddsq,
            ddadep,
            ddbnep,
            ddddpc,
            rn,
            num_rows,
            100 * (1-cumul) as cumul
          from my_sample_data a
          where ddadep = 'Y'
          model
          return all rows
          partition by (ddpsid)
          dimension by (row_number() over(partition by ddpsid order by ddddsq) as rn)
          measures (ddddsq, ddadep, ddddpc, ddbnep, 0 as cumul,
                        count(*) over(partition by ddpsid) as num_rows)
          rules automatic order (
            cumul[rn] = case
                          when nvl(ddbnep[cv(rn)],'N') = 'N'
                            then nvl(cumul[cv(rn)-1],1)- ddddpc[cv(rn)] /100
                          else nvl(cumul[cv(rn)-1],1)* (1- ddddpc[cv(rn)]/100) end
          )
--        )
--        where rn = num_rows

Данные должны быть сгруппированы по ddpsid и обработаны в порядке ddddsq.Комбинация ddpsid и ddddsq должна быть уникальной.Процент удержания находится в столбце ddddpc.Я только хочу обрабатывать строки, где ddadep = 'Y'.И, наконец, если столбец ddbnep = 'N', то я хочу просто добавить ddddpc к итоговой сумме, в противном случае, если ddbnep = 'Y', я хочу взять ddddpc в процентах (100% - промежуточная сумма) и добавить егок итоговой сумме.

Код, закомментированный, необходим, потому что я действительно хочу только последнее значение для каждого ddpsid, но оно показывает работу немного лучше без этого.

Извините за длинный вопросно это самое краткое описание, которое я могу предоставить.

Приведенный выше код показывает четыре вычета, два обычных и два чистых ранее.

  • Первый при 10% является нормальным и дает промежуточный итог 10%.
  • Второе с 10% является чистым от предыдущего.Предыдущие вычеты суммируются до 10%, поэтому остаточная сумма составляет 90%.Таким образом, этот вычет должен составлять 9%, что дает промежуточный итог 19%
  • Третий при 10% является нормальным и дает промежуточный итог 29%.
  • Финал в 10% также за вычетом предыдущего.Предыдущие вычеты суммировались до 29%, поэтому оставшаяся сумма составляет 71%.Таким образом, этот вычет должен составлять 7,1%, что дает промежуточный итог 36,1%

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

Итак, есть ли способ переписать это, не используя предложение модели и не написав функцию?

1 Ответ

2 голосов
/ 04 октября 2010

Mikey,

Для вашего запроса вам необходимо рассчитать значения на основе ранее рассчитанных значений. Это тип операции, который можно эффективно выполнить только с помощью предложения модели SQL или с помощью рекурсивного факторинга подзапроса. Последний был представлен в версии 11g Release 2. Вы можете прочитать об этом здесь в документации и здесь в моем блоге Поскольку я не знаю, какая у вас версия, я не знаю, насколько полезно это предложение.

Но почему вы хотите переписать его, не используя предложение модели?

Кстати, вы можете несколько упростить свой запрос, если используете этот вариант:

SQL> with my_sample_data as
  2  ( select 1 as ddpsid, ddddsq, ddddpc, ddbnep, ddadep
  3      from ( select 1 as ddddsq, 10 as ddddpc, 'N' as ddbnep, 'Y' as ddadep from dual union all
  4             select 2 as ddddsq, 10 as ddddpc, 'Y' as ddbnep, 'Y' as ddadep from dual union all
  5             select 3 as ddddsq, 10 as ddddpc, 'N' as ddbnep, 'Y' as ddadep from dual union all
  6             select 4 as ddddsq, 10 as ddddpc, 'Y' as ddbnep, 'Y' as ddadep from dual
  7           )
  8  )
  9  select ddpsid
 10       , ddddsq
 11       , 'Y' as ddadep
 12       , ddbnep
 13       , ddddpc
 14       , rn
 15       , num_rows
 16       , cumul
 17    from my_sample_data a
 18   where ddadep = 'Y'
 19   model
 20         partition by (ddpsid, count(*) over (partition by ddpsid) as num_rows)
 21         dimension by (row_number() over (partition by ddpsid order by ddddsq) as rn)
 22         measures (ddddsq, ddddpc, ddbnep, 0 as cumul)
 23         ( cumul[any] order by rn
 24           = case nvl(ddbnep[cv()],'N')
 25             when 'N' then
 26               nvl(cumul[cv()-1],0) + ddddpc[cv()]
 27             when 'Y' then
 28               100 - ((100 - nvl(cumul[cv()-1],0)) * (1-ddddpc[cv()]/100))
 29             end
 30         )
 31  /

    DDPSID     DDDDSQ D D     DDDDPC         RN   NUM_ROWS      CUMUL
---------- ---------- - - ---------- ---------- ---------- ----------
         1          1 Y N         10          1          4         10
         1          2 Y Y         10          2          4         19
         1          3 Y N         10          3          4         29
         1          4 Y Y         10          4          4       36.1

4 rows selected.

Надеюсь, это поможет.

С уважением, Роб.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...