1

我正在寻找一种方法来查找范围内丢失的数字。我在同一张表中有一个起始编号列和一个结束编号列。

我正在尝试获取跳过的数字。我可以获得下一个跳过的数字,但不知道如何获取不在范围内的数字列表。如果有用的话,我有一个数字表。

这是我的例子:

doc_num_begin doc_num_end
------------- -----------
20000007      20000008
20000011      20000015
20000016      20000017

我想得到20000009,20000010. 我已经搜索但无法找到如何使用开始列和结束列来执行此操作。

谢谢

4

3 回答 3

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
于 2012-12-27T15:55:52.753 回答
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 个数字时,它才会起作用,它可以很容易地扩展到更多......当然,总会有一个限制,但至少你不需要一个包含所有数字的表格)

于 2012-12-28T17:39:21.427 回答
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)
于 2012-12-27T16:15:35.463 回答