【发布时间】:2010-10-04 11:22:38
【问题描述】:
过去几天我一直在尝试解决一个相当棘手的问题。我目前正在使用 Oracle SQL 模型子句解决它,并且可能已经编写了一个函数,但我正在寻找一个使用分析函数或其他东西的简单解决方案,但无法解决任何问题。
对于给定的政策 (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 解决方案之后,我有点失望,我不能,希望我没有错过任何东西。
那么,有什么方法可以在不使用模型子句且不编写函数的情况下重写它?
【问题讨论】: