Проблемы чисел с плавающими точками, энтропия
Представим себе следующую ситуацию
У нас есть 4 столбца
- Сумма без ндс ->
sum_wo_tax
- Сумма с ндс ->
sum_w_tax
- Определитель, облагается ли ндс ->
is_wo_nds
- Исключена ли данная сумма (учитываем ли мы её, или нет) ->
excluded_from_delivery
Мы хотим посчитать коэффициент на вычет исключенных позиций из заказа, есть формула
sum(decode(t.is_wo_nds, 1, t.sum_wo_tax, t.sum_w_tax) * abs(t.excluded_from_delivery))
/
sum(decode(t.is_wo_nds, 1, decode(t.sum_wo_tax,0,1,t.sum_wo_tax), decode(t.sum_w_tax,0,1,t.sum_w_tax))) as coef
Давайте протестируем её.
Представим что есть 3 позиции, первая на 100, вторая на 100, третья на 0, первая и третья исключены, получается из суммы на 200 мы вычли 100 рублей, что равно коэффициенту 0.5
select sum(decode(t.is_wo_nds, 1, t.sum_wo_tax, t.sum_w_tax) * abs(t.excluded_from_delivery))
/
sum(decode(t.is_wo_nds, 1, decode(t.sum_wo_tax,0,1,t.sum_wo_tax), decode(t.sum_w_tax,0,1,t.sum_w_tax))) as coef
from (select 0 as is_wo_nds,
100 as sum_wo_tax,
100 as sum_w_tax,
1 as excluded_from_delivery
from dual
union all
select 0 as is_wo_nds,
100 as sum_wo_tax,
100 as sum_w_tax,
0 as excluded_from_delivery
from dual
union all
select 0 as is_wo_nds,
0 as sum_wo_tax,
0 as sum_w_tax,
1 as excluded_from_delivery
from dual) t
получаем
coef
.4975124378109452736318407960199004975124
Странно, но должно было получиться 0.5
А если убрать все обработки и мы точно понимаем, что в наших расчётах будет участвовать только sum_w_tax
и excluded_from_delivery
а то есть
select sum(t.sum_w_tax * abs(t.excluded_from_delivery)) /
sum(t.sum_w_tax) as coef
from (select 0 as is_wo_nds,
100 as sum_wo_tax,
100 as sum_w_tax,
1 as excluded_from_delivery
from dual
union all
select 0 as is_wo_nds,
100 as sum_wo_tax,
100 as sum_w_tax,
0 as excluded_from_delivery
from dual
union all
select 0 as is_wo_nds,
0 as sum_wo_tax,
0 as sum_w_tax,
1 as excluded_from_delivery
from dual) t
мы получаем
coef
.5
Решение напрашивается в округлении, но нет явного ответа, до какого знака округлять, так как исключение может быть к позиции, где sum_w_tax
стремится к бесконечности, по отношению к позиции на sum_w_tax
которая стремится к 0.
Неужели decode
так странно ведет себя?
UPD1
А что если переписать всё под констуркцию case when
?
SELECT
SUM(CASE
WHEN t.is_wo_nds = 1 THEN t.sum_wo_tax * ABS(t.excluded_from_delivery)
ELSE t.sum_w_tax * ABS(t.excluded_from_delivery)
END
) /
SUM(CASE
WHEN t.is_wo_nds = 1 THEN
CASE
WHEN t.sum_wo_tax = 0 THEN 1
ELSE t.sum_wo_tax
END
ELSE
CASE
WHEN t.sum_w_tax = 0 THEN 1
ELSE t.sum_w_tax
END
END
) as coef
from (select 0 as is_wo_nds,
100 as sum_wo_tax,
100 as sum_w_tax,
1 as excluded_from_delivery
from dual
union all
select 0 as is_wo_nds,
100 as sum_wo_tax,
100 as sum_w_tax,
0 as excluded_from_delivery
from dual
union all
select 0 as is_wo_nds,
0 as sum_wo_tax,
0 as sum_w_tax,
1 as excluded_from_delivery
from dual) t
И результат тот же
coef
.4975124378109452736318407960199004975124
т.е. в принципе условные блоки что-то вытворяют с числами?