我正在寻找一种方法来查找范围内的缺失数字。我在同一个表中有一个起始编号列和一个结束编号列。
我试图获取跳过的数字。我可以获得下一个跳过的数字,但不知道如何获得不在范围内的数字列表。我有一个数字表,如果这将是有用的。
以下是我的例子:
doc_num_begin doc_num_end
------------- -----------
20000007 20000008
20000011 20000015
20000016 20000017
我想得到20000009,20000010
。我已搜索但无法使用开始和结束列找到如何执行此操作。
由于
答案 0 :(得分:4)
如果您有数字表,那么这很简单:
select n.num
from Numbers n left outer join
RangeTable rt
on n.number between rt.doc_num_begin and doc_num_end
where rt.doc_num_begin is null
这是从数字到范围表的左外连接,然后保持那些不匹配的连接。
虽然很容易表达,但由于非等值连接,性能可能会相当差。您可能还想在数字表中添加条件,因此不要从0,1开始。 。 。,范围从20000007开始。您可以这样做:
select n.num
from Numbers n join
(select MIN(doc_num_begin) as MinVal, MAX(doc_num_end) as MaxVal from RangeTable) const
on n.number between const.MinVal and const.MaxVal left outer join
RangeTable rt
on n.number between rt.doc_num_begin and doc_num_end
where rt.doc_num_begin is null
答案 1 :(得分:1)
如果您只需找到缺失的范围,则可以使用此查询:
SELECT
t1.doc_num_end + 1 as start_missing_range,
MIN(t2.doc_num_begin) - 1 as end_missing_range
FROM
your_table t1 INNER JOIN your_table t2
ON t1.doc_num_end < t2.doc_num_begin
GROUP BY
t1.doc_num_end
HAVING
MIN(t2.doc_num_begin) - t1.doc_num_end > 1
编辑:此查询可用于扩展范围:
SELECT num+start_missing_range
FROM
(select 0 as num
union all select 1 as num
union all select 2 as num
union all select 3 as num
union all select 4 as num
union all select 5 as num
union all select 6 as num
union all select 7 as num
union all select 8 as num
union all select 9 as num) numbers inner join
(SELECT
t1.doc_num_end + 1 as start_missing_range,
MIN(t2.doc_num_begin) - 1 as end_missing_range
FROM
your_table t1 INNER JOIN your_table t2
ON t1.doc_num_end < t2.doc_num_begin
GROUP BY
t1.doc_num_end
HAVING
MIN(t2.doc_num_begin) - t1.doc_num_end > 1) rg
on end_missing_range-start_missing_range>=numbers.num
(只有当一个范围包含最多10个数字时才会起作用,它可以很容易地扩展到更多......当然,总会有一个限制,但至少你不需要一个包含所有数据的表格数字)
答案 2 :(得分:0)
您可以在任何表或示例数据库中使用已知序列号来为此目的过滤此ID。 交叉加入此ID,将扩展您所寻求的限制。
SELECT i from (select (w2.WorkOrderID-1)+(w1.WorkOrderID-1)*10000 as i
from AdventureWorks.Production.WorkOrder w1
cross join AdventureWorks.Production.WorkOrder w2
where w1.WorkOrderID<10000 and w2.WorkOrderID<10000) as MyNumbers
WHERE i BETWEEN @StartRange and @EndRange
and not exists (SELECT 1 FROM MyTable
WHERE i BETWEEN doc_num_begin doc_num_end)