很有点不好搞。 只知道首先要进行数据过滤。先对数据筛选,如6-9,6-10只取6-10;6-10,7-10,取6-10select b.begin_no,b.end_no,row_number(order by b.begin_no,b.end_no) rn from (select end_no,min(begin_no) begin_no from (select begin_no,max(end_no) end_no from tablename group by begin_no) a group by a.end_no) b;
create view stt as select b.begin_no,b.end_no,row_number(order by b.begin_no,b.end_no) rn from (select end_no,min(begin_no) begin_no from (select begin_no,max(end_no) end_no from tablename group by begin_no) a group by a.end_no) bselect min(I.begin_no) begin_no,max(I.end_no) end_no (select rn,row_number()over(order by rn) rn1 from( select c.rn from stt c,stt d where c.rn=d.rn-1 and c.end_no<d.begin_no union all select 1 from dual union all select e.rn+1 from stt e,stt f where e.rn=f.rn-1 and e.end_no<f.begin_no union all select max(g.rn) from stt g)) H,stt I where H.rn=I.rn group by round(H.rn1/2); 为了省代码,我建了个视图。
先建个测试表 create table tttt (id int, begin_no int, end_no int) insert into tttt values(1, 2, 4); insert into tttt values(2, 6, 9); insert into tttt values(3, 6, 10); insert into tttt values(4, 7, 12); insert into tttt values(5, 11, 14); insert into tttt values(6, 16, 18); insert into tttt values(7, 17, 18); insert into tttt values(8, 18, 20); insert into tttt values(9, 22, 24);查询sql:select begin_no ,end_no from ( select rownum as id ,temp.end_no from ( select distinct a.end_no from tttt a where not exists(select 1 from tttt b where a.end_no>=b.begin_no and a.end_no<b.end_no and a.id<>b.id) order by a.end_no) temp ) end_table, ( select rownum as id ,temp.begin_no from ( select distinct a.begin_no from tttt a where not exists(select 1 from tttt b where a.begin_no>b.begin_no and a.begin_no<=b.end_no and a.id<>b.id) order by a.begin_no) temp ) begin_table where end_table.id = begin_table.id思路: 可以把时间段看成是端点是begin_no和end_no的放成一列的平行的一些线段。并且在坐标系内,平行于x轴,如果把线段按照起点从小到大的顺序摆放,则连续的线段端点重合在别的线段内(可以把起点和终点的值都想成是坐标系中的横坐标)。则题目就成了求各个不连续的(垂直于x轴做垂线,跟别的线段没有交叉的)起点和终点。 如果一个起始点或终点的垂线,没有落在其他线段的范围内,则它是断开点。一条连续的线段,有起点,必有终点。所以起点和终点的个数一定相等。可以分别求起点和终点,然后按从大到小排序,把行对应起来。就是相应的起点和终点。两者之间就是连续的线段的长。
注意查询sql是一句sql哦,要一次执行,^_^
不错,思路很好。 MARK! 比我的要在代码上少很多。大致看了一下,你的SQL没什么问题,把我前面的过滤也直接在where中实现了。我怀疑我的代码在row_number()over(order by rn) rn1这一步会通不过,因为没有指定别名,应该在给union的整个集合起个别名的,当时写的时候忘掉了。也没环境去调试。 你这个SQL真的很经典!
id, begin_no, end_no
__________________________________________
1, 2, 4
2, 6, 9
3, 6, 10
4, 7, 12
5, 11, 14
6, 16, 18
7, 17, 18
8, 18, 20
9, 22, 24
.......
__________________________________________那我希望得到所有出现在上述开始号码和结束号码之间的号码段记录集,如下:
__________________________________________
2, 4
6, 14
16, 20
22, 24
__________________________________________
只知道首先要进行数据过滤。先对数据筛选,如6-9,6-10只取6-10;6-10,7-10,取6-10select b.begin_no,b.end_no,row_number(order by b.begin_no,b.end_no) rn
from
(select end_no,min(begin_no) begin_no
from
(select begin_no,max(end_no) end_no
from tablename
group by begin_no) a
group by a.end_no) b;
as
select b.begin_no,b.end_no,row_number(order by b.begin_no,b.end_no) rn
from
(select end_no,min(begin_no) begin_no
from
(select begin_no,max(end_no) end_no
from tablename
group by begin_no) a
group by a.end_no) bselect min(I.begin_no) begin_no,max(I.end_no) end_no
(select rn,row_number()over(order by rn) rn1
from(
select c.rn
from stt c,stt d
where c.rn=d.rn-1 and c.end_no<d.begin_no
union all
select 1 from dual
union all
select e.rn+1
from stt e,stt f
where e.rn=f.rn-1 and e.end_no<f.begin_no
union all
select max(g.rn)
from stt g)) H,stt I
where H.rn=I.rn
group by round(H.rn1/2);
为了省代码,我建了个视图。
create table tttt (id int, begin_no int, end_no int)
insert into tttt values(1, 2, 4);
insert into tttt values(2, 6, 9);
insert into tttt values(3, 6, 10);
insert into tttt values(4, 7, 12);
insert into tttt values(5, 11, 14);
insert into tttt values(6, 16, 18);
insert into tttt values(7, 17, 18);
insert into tttt values(8, 18, 20);
insert into tttt values(9, 22, 24);查询sql:select begin_no ,end_no from
(
select rownum as id ,temp.end_no from (
select distinct a.end_no from tttt a
where not exists(select 1 from tttt b where a.end_no>=b.begin_no and a.end_no<b.end_no and a.id<>b.id)
order by a.end_no) temp
) end_table,
(
select rownum as id ,temp.begin_no from (
select distinct a.begin_no from tttt a
where not exists(select 1 from tttt b where a.begin_no>b.begin_no and a.begin_no<=b.end_no and a.id<>b.id)
order by a.begin_no) temp
) begin_table
where end_table.id = begin_table.id思路:
可以把时间段看成是端点是begin_no和end_no的放成一列的平行的一些线段。并且在坐标系内,平行于x轴,如果把线段按照起点从小到大的顺序摆放,则连续的线段端点重合在别的线段内(可以把起点和终点的值都想成是坐标系中的横坐标)。则题目就成了求各个不连续的(垂直于x轴做垂线,跟别的线段没有交叉的)起点和终点。
如果一个起始点或终点的垂线,没有落在其他线段的范围内,则它是断开点。一条连续的线段,有起点,必有终点。所以起点和终点的个数一定相等。可以分别求起点和终点,然后按从大到小排序,把行对应起来。就是相应的起点和终点。两者之间就是连续的线段的长。
MARK!
比我的要在代码上少很多。大致看了一下,你的SQL没什么问题,把我前面的过滤也直接在where中实现了。我怀疑我的代码在row_number()over(order by rn) rn1这一步会通不过,因为没有指定别名,应该在给union的整个集合起个别名的,当时写的时候忘掉了。也没环境去调试。
你这个SQL真的很经典!