各位ORACLE牛人,今天遇到一个很邪的问题,以前没有遇到过。
我是在存储过程中遇到的。我把我的问题简化为如下问题。大家有没有遇到过?
有一张表 T1
两个字段 C1 VARCHAR2,C2 NUMBER
T1中的数据由一系统计算得到
如下:
C1 C2
A 100
B 900
C 2589
D 123.6598
E 900
F 120
G 100
执行如下排名语句:
select C1,C2, dense_rank() over (order by C2 DESC) MC FROM T1
C1 C2 MC
C 2589 1
B 900 2
E 900 2
D 123.6598 3
F 120 4
A 100 5
G 100 6
发现,B,E值相同,排名相同。
而A,G值相同,排名却不同
百思不得其解
没办法
select (select C2 from T1 where C1= 'A'),
(select C2 from T1 where C1= 'G'),
(select C2 from T1 where C1= 'A') -
(select C2 from T1 where C1= 'G')
from dual
--------------------------------
100 100 1E-36
TNND ,计算过程出现精度问题。这个真奇怪,大家遇到吗?
肉眼看不出来呀。
------解决方案--------------------
在SQLPLUS下这样
sql>set numwidth 30
然后执行这个语句看一下,肯定值不一样
select (select C2 from T1 where C1= 'A'),
(select C2 from T1 where C1= 'G'),
(select C2 from T1 where C1= 'A') -
(select C2 from T1 where C1= 'G')
from dual
------解决方案--------------------
T1中的数据由一系统计算得到???
说明A 100 5
G 100 6
根本就不是100,你的计算也证明了
和在SQLPLUS下这样
sql>set numwidth 30
没有任何关系,你设成set numwidth 2结果也是一样的,sqlplus客户端命令只会改变显示效果,不会改变SQL的执行结果
------解决方案--------------------
C2 类型是什么?是不是你的类型指定了精度度?
------解决方案--------------------
- SQL code
SQL> with t1 as ( 2 select 'A' c1, 100 c2 from dual union all 3 select 'B' c1, 900 c2 from dual union all 4 select 'C' c1, 2589 c2 from dual union all 5 select 'D' c1, 123.6598 c2 from dual union all 6 select 'E' c1, 900 c2 from dual union all 7 select 'F' c1, 120 c2 from dual union all 8 select 'G' c1, 100 c2 from dual 9 ) 10 select C1,C2, dense_rank() over (order by C2 DESC) MC FROM T1 11 / C1 C2 MC-- ---------- ----------C 2589 1E 900 2B 900 2D 123.6598 3F 120 4A 100 5G 100 5 7 rows selected
------解决方案--------------------
可见,你的计算并非是2个值都是100,可能有小数位上的误差
------解决方案--------------------
听说这是oracle的一个bug
------解决方案--------------------
没有发现类似的情况
create table t1(c1 varchar2(10),c2 number);
insert into t1 select 'A',100 from dual;
insert into t1 select 'B',900 from dual;
insert into t1 select 'C',2589 from dual;
insert into t1 select 'D',123.6598 from dual;
insert into t1 select 'E',900 from dual;
insert into t1 select 'F',120 from dual;
insert into t1 select 'G',100 from dual;
select c1,c2,dense_rank()over(order by c2 desc) from t1
C 2589 1
E 900 2
B 900 2
D 123.6598 3
F 120 4
A 100 5
G 100 5