SQL – 范围是否在连续范围内

我真的很难过……

假设我有一个“有效数字”表,其中包含BEGIN_NUM和END_NUM列,表示一系列有效数字.该表看起来像这样:

ID BEGIN_NUM END_NUM
-- --------- -------
 A       1      10         
 B      11      20
 C      21      30
 D      55      70

我们给出了一个范围的开始数和结束数.我需要开发一个SQL查询来查看该数字范围是否都是有效数字.

简单的情况:给定2和8作为我们的开始和结束我们的范围,这将通过,因为它落在行A的范围内.

硬情况:(#1)给定5和15,这将通过,因为它属于行A和行B,这基本上是彼此的连续,形成跨越两行的一个大范围. (1-10& 11-20 = 1-20).

给出5和25的(#2),除了它跨越几行而不是两行之外,它也会以与(#1)相同的理由通过. (1-10& 11-20& 21-30 = 1-30)

(#3)给定27和57,这将失败,因为即使开始和结束数字落在一个范围内,行C和行D之间也存在间隙(因此这将使我们给定范围内的数字31-54无效) .

我真的不必使用此查询返回任何数据,只显示该范围包含所有有效数字.如果重要,请使用Oracle.

这是我到目前为止:

select count(*) 
from (select start_num, end_num
    from ae_valid_vendor_nums
    where '5' BETWEEN start_num AND end_num) tbl1,
 (select start_num, end_num
    from ae_valid_vendor_nums
    where '25'  BETWEEN start_num AND end_num) tbl2
where (tbl1.end_num - tbl2.start_num = -1) 
OR (tbl1.start_num = tbl2.start_num AND tbl1.end_num = tbl2.end_num)

谢谢你的帮助!

最佳答案 有趣的小问题.我们的想法是计算每组内的重叠,将重叠相加,然后与实际范围进行比较.以下查询通过一些示例执行此操作.它输出的内容比您要求的多一点,但这应该有助于您了解它的工作原理:

with ValidNumbers as (
     select 1 as begin_num, 10 as end_num from dual union all
     select 11, 20 from dual union all
     select 21, 30 from dual union all
     select 55, 70 from dual
    )
select v_begin, v_end,
       sum(1 + (case when v_end >= vn.end_num then vn.end_num else v_end end) -
           (case when v_begin >= vn.begin_num then v_begin else vn.begin_num end)
          ) as SumInRecords,
       max(1 + v_end - v_begin) as TheRange,
       (case when sum(1 + (case when v_end >= vn.end_num then vn.end_num else v_end end) -
                      (case when v_begin >= vn.begin_num then v_begin else vn.begin_num end)
                     ) =
                   max(1 + v_end - v_begin)
             then 'All' else 'Missing'
         end)
from ValidNumbers vn cross join
     (select 2 as v_begin, 8 as v_end from dual union all
      select 2, 18 from dual union all
      select 2, 28 from dual union all
      select 2, 38 from dual
     ) const
where v_begin <= vn.end_num and
      v_end >= vn.begin_num
group by v_begin, v_end;
点赞