我有一个相当棘手的问题,我过去几天一直试图解决这个问题。我目前正在使用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的最后一个值,但如果没有它,它会显示更好的工作。
很抱歉这个很长的问题,但它是关于我能提供的最简洁的描述。
上面的代码显示了四个扣除,两个正常扣除和两个先验扣除。
尝试两三天尝试找到一个SQL解决方案后,我有点失望,我不能,希望我不会错过任何东西。
那么,有没有办法在不使用model子句且不编写函数的情况下重写它?
答案 0 :(得分:2)
米奇,
对于您的查询,您需要根据以前计算的值计算值。 这是一种只能使用SQL Model Clause或Recursive Subquery Factoring有效完成的操作。后者是在版本11g第2版中引入的。您可以阅读here in the documentation和here 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.
希望这有帮助。
此致 罗布。