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

これは、数値から範囲テーブルへの左外部結合を行ってから、一致しないものを保持しています。

かなり簡単に表現できますが、等結合ではないため、パフォーマンスがかなり低下する可能性があります。数字の表に条件を入れたいと思うかもしれません。. .、範囲が 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 に答える