我真的很难过......
假设我有一个“有效数字”表,其中列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)
给出27和57的(#3),这将失败,因为即使开始和结束数字落在一个范围内,行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)
感谢您的帮助!
答案 0 :(得分:1)
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;
答案 1 :(得分:1)
一种方法是使用计数表,然后将计数计数与两个终点的差异进行比较(加一,因为它包括在内)
这是例如
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),
tally
AS (SELECT LEVEL num
FROM dual
CONNECT BY LEVEL <= 100
ORDER BY LEVEL),
test
AS (SELECT t.num
FROM validnumbers v
inner join tally t
ON v.begin_num <= t.num
AND v.end_num >= t.num
WHERE t.num >= 27
AND t.num <= 57)
SELECT Count(num),
(57 - 27) + 1
FROM test
生成此结果的正确失败案例
COUNT(NUM) (57-27)+1
---------- ----------
7 31
用25和5代替57和27给我们一个正确的传球
COUNT(NUM) (25-5)+1
---------- ----------
21 21