如题:为什么“2010-6-23 2 2010-6-24 0 5”也被查出来了!
create table ta (id number,ctime date, amount number);insert into ta (id, ctime, amount)
values (1, to_date('23-06-2010 17:51:00', 'dd-mm-yyyy hh24:mi:ss'), 6);
insert into ta (id, ctime, amount)
values (2, to_date('23-06-2010 17:52:00', 'dd-mm-yyyy hh24:mi:ss'), 3);
insert into ta (id, ctime, amount)
values (3, to_date('23-06-2010 17:53:00', 'dd-mm-yyyy hh24:mi:ss'), 3);
insert into ta (id, ctime, amount)
values (4, to_date('23-06-2010 17:54:00', 'dd-mm-yyyy hh24:mi:ss'), 11);
insert into ta (id, ctime, amount)
values (5, to_date('23-06-2010 17:55:00', 'dd-mm-yyyy hh24:mi:ss'), 6);
insert into ta (id, ctime, amount)
values (6, to_date('23-06-2010 17:56:00', 'dd-mm-yyyy hh24:mi:ss'), 11);
insert into ta (id, ctime, amount)
values (7, to_date('23-06-2010 23:56:00', 'dd-mm-yyyy hh24:mi:ss'), 1);
insert into ta (id, ctime, amount)
values (8, to_date('24-06-2010 00:01:00', 'dd-mm-yyyy hh24:mi:ss'), 3);
commit;SQL> select *
  2     from(
  3          select ctime,next_time,(next_time - ctime)*24*60
  4           from (select ctime,
  5                       lead(ctime) over(order by ctime) next_time
  6                  from (select ctime,
  7                               row_number() over(partition by ctime order by ctime) rn
  8                          from ta
  9                         )
 10                          where rn = 1
 11                       ) x
 12           )m
 13     where (m.next_time - m.ctime)*24*60 < 5;
 
CTIME       NEXT_TIME   (NEXT_TIME-CTIME)*24*60
----------- ----------- -----------------------
2010-6-23 1 2010-6-23 1                       1
2010-6-23 1 2010-6-23 1                       1
2010-6-23 1 2010-6-23 1                       1
2010-6-23 1 2010-6-23 1                       1
2010-6-23 1 2010-6-23 1                       1
2010-6-23 2 2010-6-24 0                       5
 
6 rows selectedSQL>  select (to_date('2010-6-24 00:01:00','yyyy-mm-dd hh24:mi:ss')-to_date('2010-6-23 23:56:00','yyyy-mm-dd hh24:mi:ss'))*24 * 60  interval
  2     from dual;
 
  INTERVAL
----------
         5  明明时间间隔是5, 5<5 为false,但是数据还是被查询出来了,迷惑中!

解决方案 »

  1.   


    select *
       from(
            select ctime,next_time,(next_time - ctime)*24*60
             from (select ctime,
                         lead(ctime) over(order by ctime) next_time
                    from (select ctime,
                                 row_number() over(partition by ctime order by ctime) rn
                            from ta
                           )
                            where rn = 1
                         ) x
             )m
       where m.ctime + interval '5' minute > m.next_time;CTIME                 NEXT_TIME             (NEXT_TIME-CTIME)*24*60
    --------------------- --------------------- -----------------------
    2010-06-23 17:51:00   2010-06-23 17:52:00                         1
    2010-06-23 17:52:00   2010-06-23 17:53:00                         1
    2010-06-23 17:53:00   2010-06-23 17:54:00                         1
    2010-06-23 17:54:00   2010-06-23 17:55:00                         1
    2010-06-23 17:55:00   2010-06-23 17:56:00                         1把where条件改一下,用interval比较要精确一点。
      

  2.   

    的确应该是精度的问题,我们看到的5是因为保留位后面很小的位数看不到了,但是在显示前肯定还是原值,你可以分别作将你的最后提供的SQL做一下两个实验:
    1、直接减去5SQL> SELECT (to_date('2010-6-24 00:01:00','yyyy-mm-dd hh24:mi:ss')-to_date('2010-6-23 23:56:00','yyyy-mm-dd hh24:mi:ss'))*24 * 60 - 5
      2  FROM dual
      3  ;(TO_DATE('2010-6-2400:01:00','
    ------------------------------
                            -3E-38
    难道ORACLE算错了?不太可能吧,这么大型个数据库即使有点小BUG也应该是可以解决的,不能反这么大的错误吧,看得出来是在小数点后38位有个3在。此时我们姑且相信自己的理论,做一个四舍五入操作,或者操作完毕后做四舍五入操作,看看结果:SQL> SELECT round((to_date('2010-6-24 00:01:00','yyyy-mm-dd hh24:mi:ss')-to_date('2010-6-23 23:56:00','yyyy-mm-dd hh24:mi:ss'))*24 * 60) - 5
      2      FROM dual
      3  ;ROUND((TO_DATE('2010-6-2400:01
    ------------------------------
                                 0
    SQL> SELECT round((to_date('2010-6-24 00:01:00','yyyy-mm-dd hh24:mi:ss')-to_date('2010-6-23 23:56:00','yyyy-mm-dd hh24:mi:ss'))*24 * 60 - 5)
      2      FROM dual
      3  ;ROUND((TO_DATE('2010-6-2400:01
    ------------------------------
                                 0
    也就是你要对比精度极高的数据就需要这样做一下操作才是准确的数据,后面保留位的数字几乎是由于计算中的精度导致,也可以算是误差,这也是计算机不可避免的一些误差,可以忽略的,ORACLE不会在你可以见的位置出现误差,那这门数据库的麻烦就大了。