使用case when子句和log函数创建表

时间:2015-02-25 21:06:50

标签: sql oracle oracle11g

我有桌子利润:

date    name    percentage 
xxx      yyy      10
xxd      ddd     -10
...

我想按log(百分比)

创建一个新表
date    name    percentage  logP
xxx      yyy      10        xxx
xxd      ddd     -10        xxx

这是我的代码:

create table logProfit as
Select a.*,
case when a.percentage=0 then NULL 
when a.percentage=-100 then NULL
when a.percentage<0 and a.percentage > -100 then -log(10,a.percentage)
else log(10,a.percentage) end  logP
from profit a;

但它有错误,如

"SQL error: ORA-01428: '-8.2272727272727272727272727272727272727' out of arrange
01428. 00000 -  "argument '%s' is out of range", 

是我的情况,当条款错了吗?

1 个答案:

答案 0 :(得分:2)

您无法记录负数,这是您尝试处理的情况:

when a.percentage<0 and a.percentage > -100 then -log(10,a.percentage)

但你在错误的地方有减号;或者你想要两个。目前,如果您的浮动百分比值为-8.227 ......您还在评估:

log(10, -8.227)

获得ORA-01428: argument '-8.227' is out of range,然后才能否定它。所以你需要否定函数调用中的百分比;之一:

when a.percentage<0 and a.percentage > -100 then log(10,-a.percentage)

when a.percentage<0 and a.percentage > -100 then -log(10,-a.percentage)

对于更简单的百分比-8.227,它将分别给你.915241497或-.915241497。


顺便提一下,您可以使用sign() functionthe abs() function来处理负数,从而简化您的逻辑;那么你只需要明确处理零:

sign(a.percentage) * log(10,
  case when a.percentage != 0 then abs(a.percentage) else null end)

或者如果您认为有必要,处理-100;不知道为什么这被视为一个特例:

sign(a.percentage) * log(10,
  case when a.percentage != 0 and a.percentage > -100
    then abs(a.percentage) else null end)

用于比较的快速演示:

with profit as (
  select cast(-100 as float) as percentage from dual
  union all select -0.5 from dual
  union all select 0 from dual
  union all select 0.5 from dual
  union all select 100 from dual
)
Select a.*,
  case when a.percentage=0 then NULL 
    when a.percentage=-100 then NULL
    when a.percentage<0 and a.percentage > -100 then -log(10,-a.percentage)
    else log(10,a.percentage) end as orig_logP,
  sign(a.percentage) * log(10,
    case when a.percentage != 0 and a.percentage > -100
      then abs(a.percentage) else null end) as new_logP
from profit a;

PERCENTAGE  ORIG_LOGP   NEW_LOGP
---------- ---------- ----------
      -100
       -.5 .301029996 .301029996
         0
        .5    -.30103    -.30103
       100          2          2

或者正如David Faber指出的那样,如果你真的想要自然日志,请使用the ln() function

sign(a.percentage) * ln(case when a.percentage != 0 and a.percentage > -100
    then abs(a.percentage) else null end) as logP

得到:

PERCENTAGE       LOGP
---------- ----------
      -100
       -.5 .693147181
         0
        .5 -.69314718
       100 4.60517019