问题描述
SELECT decode(detl_cd,'AAA',trunc(amt * to_number(pct) / 100,2),'BBB','CCC',(amt-trunc(amt * to_number(pct) / 100,2))
INTO trans_amount
FROM dual;
我从游标中获取值 detl_cd,从输入文件中获取 amt。
Select tb1.id,tb2.detl_cd,tb2.pct
from tb1
join tb2 on tb1.agent_code=tb2.agent_code
where tb1.id='1';
每个 id 有 3 个 detl cd,每个 detl 代码有不同的计算。如何在解码中避免硬编码。创建表格不是一种选择。
输入文件
ID Amount
1 1000
2 2500
3 350
Id 1 & 2 属于分配了 3 个不同 detl cd 和不同百分比 (pct) 的组。
ID Detl_cd Amount
1 AAA1 250
1 BBB1 250
1 CCC1 750
2 AAA3 625
2 BBB3 625
2 CCC3 1875
3 350
每个 ID 有 3 个不同的 detl_cd,但 AAA1 和 AAA2 的计算是相同的,因此 BBB 和 CCC 也是如此。
解决方法
创建表格不是一种选择。
您需要一个存储一组业务规则而不在代码中指定业务规则的解决方案。但也无需创建表来存储这些规则。
那只留下一个用户定义的函数。
create or replace function calc_amount
( p_detl_cd in varchar2,p_amt in number,p_pct in number )
return number
as
begin
case substr(p_detl_cd,1,3)
when 'AAA' then return trunc(p_amt * to_number(p_pct) / 100,2);
when 'BBB' then return trunc(p_amt * to_number(p_pct) / 100,2);
when 'CCC' then return (p_amt-trunc(p_amt * to_number(p_pct) / 100,2);
end case;
end calc_amount;
您可以在 SQL 或 PL/SQL 中调用此函数。你对表和文件有点含糊,所以我不太清楚数据来自哪里,但它在 PL/SQL 中可能看起来像这样:
trans_amount := calc_amount(detl_cd,amt,pct);
我希望避免对“AAA”进行硬编码,因为这些代码将来可能会更改/替换,我不希望返工
或者代码可能会改变,计算也会改变。没关系。残酷的事实是,您必须在某处对代码及其相关规则进行硬编码。不可能有一个无限灵活的软编码系统。
表格是最容易维护的东西,它为您提供了最大的灵活性。但是您需要使用动态 SQL 或函数来应用计算;一个功能将是我的偏好。最糟糕的解决方案是将代码和计算放在与输入文件同时加载的外部配置文件中。
或者,尝试为“可能会改变”设置一个值。代码(或计算)发生变化的可能性有多大?多常?计算一下,也许您会发现更改不太可能或非常罕见,最简单的选择是坚持解码并在出现这种情况时接受返工。
顺便说一句,您确定您指的是 trunc()
而不是 round()
?
我猜你可能想要
WITH DATA AS
(Select tb1.id,tb2.detl_cd,tb2.pct
from tb1
join tb2 on tb1.agent_code=tb2.agent_code
where tb1.id='1')
SELECT decode(detl_cd,'AAA',trunc(amt * to_number(pct) /
100,2),'BBB',trunc(amt * to_number(pct) / 100,'CCC',(amt-trunc(amt * to_number(pct) / 100,2))
as trans_amount
FROM Data;