问题描述
有以下需求: 数据库为oracle有一张表 tel(varchar2),up_time(timestamp)数据: 1,2014-3-31 12:20:301,2014-3-31 12:20:351,2014-3-31 12:20:361,2014-3-31 12:21:011,2014-3-31 12:21:031,2014-3-31 12:21:051,2014-3-31 12:21:111,2014-3-31 12:21:151,2014-3-31 12:21:18想得到以下数据:1,2014-3-31 12:20:301,2014-3-31 12:20:351,2014-3-31 12:21:011,2014-3-31 12:21:111,2014-3-31 12:21:18(大体意思就是以查询出来的第一条数据为基准 找到下一条间隔时间大于等于5秒的数据,然后以下一条数据为基准,再找到它的下一条大于等于5秒的数据,以此类推)求大神解~~~~~~~ 问题补充:初始化脚本:create table t_test( tel VARCHAR2(12) not null, up_time TIMESTAMP not null);insert into t_test(tel,up_time) values('1', to_timestamp('2014-3-31 12:20:30','yyyy-MM-dd HH:mi:ss'));insert into t_test(tel,up_time) values('1', to_timestamp('2014-3-31 12:20:35','yyyy-MM-dd HH:mi:ss'));insert into t_test(tel,up_time) values('1', to_timestamp('2014-3-31 12:20:36','yyyy-MM-dd HH:mi:ss'));insert into t_test(tel,up_time) values('1', to_timestamp('2014-3-31 12:21:01','yyyy-MM-dd HH:mi:ss'));insert into t_test(tel,up_time) values('1', to_timestamp('2014-3-31 12:21:03','yyyy-MM-dd HH:mi:ss'));insert into t_test(tel,up_time) values('1', to_timestamp('2014-3-31 12:21:05','yyyy-MM-dd HH:mi:ss'));insert into t_test(tel,up_time) values('1', to_timestamp('2014-3-31 12:21:11','yyyy-MM-dd HH:mi:ss'));insert into t_test(tel,up_time) values('1', to_timestamp('2014-3-31 12:21:15','yyyy-MM-dd HH:mi:ss'));insert into t_test(tel,up_time) values('1', to_timestamp('2014-3-31 12:21:18','yyyy-MM-dd HH:mi:ss'));commit;
解决方案
select x.*,sys_connect_by_path(to_char(x.up_time,'yyyy-MM-dd hh:mi:ss'), '/' ) from ( select a.*,(select min(up_time) from t_test b where b.up_time >= a.add_time) next_time from( select t.*,t.up_time + 1/(24*60*60)*5 add_time from t_test t ) a) xstart with x.up_time = to_date('2014-03-31 12:20:30','yyyy-MM-dd hh:mi:ss')connect by prior x.next_time = x.up_time主要思路是通过oracle的connect by 递归实现,但实现的时候有个问题,就是你的表缺少字段来连接上下记录,所以要自己模拟上面sql主要分成以下几个步骤:1.select t.*,t.up_time + 1/(24*60*60)*5 add_time from t_test t增加一列表示up_time加上5秒是哪个时间,结果如果下:引用12014-03-31 12:20:302014-03-31 12:20:3512014-03-31 12:20:352014-03-31 12:20:4012014-03-31 12:20:362014-03-31 12:20:4112014-03-31 12:21:012014-03-31 12:21:0612014-03-31 12:21:032014-03-31 12:21:0812014-03-31 12:21:052014-03-31 12:21:1012014-03-31 12:21:112014-03-31 12:21:1612014-03-31 12:21:152014-03-31 12:21:2012014-03-31 12:21:182014-03-31 12:21:232.select a.*,(select min(up_time) from t_test b where b.up_time >= a.add_time) next_time from( select t.*,t.up_time + 1/(24*60*60)*5 add_time from t_test t ) a在步骤一的基础上,增加一列next_time,即根据步骤一计算出的列add_time(也就是up_time加上5秒的值)来得到此add_time与原表数据中的up_time哪个最近。结果如下:引用12014-03-31 12:20:302014-03-31 12:20:352014-03-31 12:20:3512014-03-31 12:20:352014-03-31 12:20:402014-03-31 12:21:0112014-03-31 12:20:362014-03-31 12:20:412014-03-31 12:21:0112014-03-31 12:21:012014-03-31 12:21:062014-03-31 12:21:1112014-03-31 12:21:032014-03-31 12:21:082014-03-31 12:21:1112014-03-31 12:21:052014-03-31 12:21:102014-03-31 12:21:1112014-03-31 12:21:112014-03-31 12:21:162014-03-31 12:21:1812014-03-31 12:21:152014-03-31 12:21:2012014-03-31 12:21:182014-03-31 12:21:233.这就可以根据步骤二得到的表结构进行oracle递归查询了,查询条件就是根据next_time=up_time来进行
解决方案二:
为什么不在TABLE Design的时候考虑扩展一个Column出来保存与上一条Record的时间差呢?
解决方案三:
没有想到好的方法,但是为什么非要用sql呢,可以用程序处理,如果数据量不大的话,可以一次读出,在程序中操作,速度也很快。