根据SQL中先前行的总和查找总扣减额

时间:2010-10-04 11:22:38

标签: sql oracle oracle10g

我有一个相当棘手的问题,我过去几天一直试图解决这个问题。我目前正在使用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解决方案后,我有点失望,我不能,希望我不会错过任何东西。

那么,有没有办法在不使用model子句且不编写函数的情况下重写它?

1 个答案:

答案 0 :(得分:2)

米奇,

对于您的查询,您需要根据以前计算的值计算值。 这是一种只能使用SQL Model Clause或Recursive Subquery Factoring有效完成的操作。后者是在版本11g第2版中引入的。您可以阅读here in the documentationhere in a blogpost of mine。 由于我不知道你的版本是什么,我不知道这个建议有多么有用。

但是为什么要在不使用model子句的情况下重写它呢?

顺便说一句,如果您使用此变体,可以稍微简化一下您的查询:

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.

希望这有帮助。

此致 罗布。