Итак, вы пишете функцию PL / SQL, но пытаетесь выполнить всю логику простым запросом SQL.Я думаю, что это, безусловно, возможно сделать с запросом SQL, но, поскольку ваша исходная логика структурирована как цикл, вам может быть проще использовать структуру цикла PL / SQL.
CREATE OR REPLACE function CalculateIncomeTax2(taxableIncome NUMBER)
return NUMBER
AS
IncomeTax NUMBER (10,2) := 0;
TaxableRemainder NUMBER := taxableIncome;
BEGIN
for r in (select tax_id, tax_percentage, tax_cummulative_amount
from incometax
order by tax_id)
loop
if TaxableRemainder > r.tax_cummulative_amount then
TaxableRemainder := TaxableRemainder - r.tax_cummulative_amount;
incometax := incometax + (r.tax_cummulative_amount * r.tax_percentage / 100);
else
incometax := incometax + (TaxableRemainder * r.tax_percentage / 100);
exit;
end if;
end loop;
return IncomeTax;
end;
/
Для вашего примераЯ получаю CalculateIncomeTax2(2000) = 288.08
.Это немного отличается от того, что вы обычно получаете с калькулятором (288,075), потому что вы определили IncomeTax как NUMBER (10,2) с точностью до 2. Но, возможно, это то, что вы хотите?
Редактировать: Такв вашем SQL-запросе главное, чего вам не хватает, - это чтобы итоговая сумма суммы налога для каждой строки была необходима аналитическая / оконная функция .Вот пример того, как вы могли бы сделать то же самое вычисление в простом запросе SQL.(Вы можете значительно упростить этот запрос, но я думаю, что таким образом он более читабелен - вы можете легко посмотреть на подзапрос, чтобы увидеть, как создаются данные.)
select sum(tax_component)
from (
select tax_id, tax_percentage, tax_cummulative_amount,
taxableRemainder,
case when taxableRemainder > tax_cummulative_amount
then (tax_cummulative_amount * tax_percentage / 100)
else (taxableRemainder * tax_percentage / 100)
end as tax_component
from (
select tax_id, tax_percentage, tax_cummulative_amount,
nvl(2000-sum(tax_cummulative_amount)
over (order by tax_id
rows between unbounded preceding and 1 preceding),
2000)
as taxableRemainder
from incometax) it
)
;