2017-10-30 8 views
0

数字のリストを調べて、リストが数値順にソートされているときに最初の数字が見つからないようにしたい。このリストにない数値でソートされた最初の整数を見つけるにはどうすればよいですか?

たとえば、クエリから数字のこの結果セットを考えてみます。

A 
--- 
0 
1 
3 
4 
5 

を、私は最高に最低から番号順にこのリストを通過し、リストから欠落している最初の番号を返すために、クエリを必要とします完全で数値的にソートされた数。上記の例では、クエリはを返します。以下はいくつかの例です。要件:値0でチェックを開始しなければならず、数値ソートリストにない最初の値を返さなければならず、1つの数値だけを返す必要があります。

A 
--- 
1 
3 
4 
5 

/* return 0 */ 

A 
--- 
0 
1 
2 
3 
4 
5 
8 
9 

/* return 6*/ 

答えて

0

使用not exists

select top 1 a + 1 
from t 
where not exists (select 1 from t t2 where t2.a = t.a + 1) 
order by a; 
+0

外部結合はもっと効果的ではありませんか? – Basilevs

+0

これは動作しますが、私はそれをあまり理解していません。 WHERE句は何をしていますか?それは、それ自体がテーブルに加わり、 't2'の最初の行と' t'の最後の行を参加から除外しているようです。次に、返される行数の1倍の定数を選択します。しかし、それは、このサブクエリが行を返さない場所を見つけることを望んでいます。これは混乱するところです。 – DarthVoid

+1

2回目のテストに失敗します(0がありません) – Basilevs

1

クエリ次の順序で最初の不在の行を見つけますが、ゼロとシーケンス開始までの番号を見つけることができない:

SELECT 
    MIN(T1.a + 1) 
    FROM A as T1 LEFT OUTER JOIN A as T2 ON T1.a + 1 = T2.a 
    WHERE T1.a > -1 AND T2.a IS NULL; 

基本的な考え方 - すべて見つけます行+前の行をペアにし、不完全なペアを使用して欠落している値を導出します。

イラスト:

CREATE TABLE A (a int); 
INSERT INTO A VALUES (0) ; 
INSERT INTO A VALUES (1) ; 
INSERT INTO A VALUES (2) ; 
INSERT INTO A VALUES (3) ; 
--INSERT INTO A VALUES (4) ; 
INSERT INTO A VALUES (5) ; 
INSERT INTO A VALUES (6) ; 
INSERT INTO A VALUES (7) ; 

SELECT 
    T1.a, T2.a FROM A as T1 LEFT OUTER JOIN A as T2 ON T1.a + 1 = T2.a; 

出力:NOTは、MS SQL上に存在するよりも、

0 1 
1 2 
2 3 
3 (null) 
5 6 
6 7 
7 (null) 

このソリューションis slower。私はこの事実が魅力的であることを見出し、結合はずっと簡単に最適化するべきです。

+0

待機します。 – DarthVoid

+0

最初の声明は、不足を捕らえることができないということです0 – Basilevs

+0

それで、あなたは欠けている0のために働く解決策を知らないのですか? – DarthVoid

0

は、再帰CTEを使用します。

declare @upperBound int 
select @upperBound = max(x) from yourTable  

;with a as (
select 0 x 
union ALL 
SELECT x + 1 
from a 
where a < @upperBound 
) 

select min(a.x) 
from yourTable yt 
right join a 
    on yt.x = a.x 
where yt.x is null 
+0

整数リストの上限を指定することはできません。 – DarthVoid

+0

@Darthあなたは99以外の数字を使用することを意味しますか? –

+0

私があなたの答えを正しく理解すれば、あなたはチェックするために任意の高い価値を選んだのです。私は自分の状況では上限を取ることができません。 – DarthVoid

0

私は数字のテーブルを使用することになり、また、集計テーブルと呼ばれます。必要に応じてオンザフライで作成することができますが、それは実際には効率が悪く、一般的に使用されているため、各サーバーに完全に索引が付けられています。それらについての記事の多くがあります - あなたはTALLYテーブルを構築していると、列もTALLYと呼ばれていると仮定し、ここで簡単な例ではNumber tables explained part 1

だ、あなたのテーブルはデータであり、チェックするための列はID

が最高を見つけることです私たちがチェックする必要がある番号。 (@Upperbound) 次に、集計表から有効な行をすべて選択し、データ表を外部結合し、一致しない行のみを保持します。最下のタリーはあなたが望む番号です

DECLARE @UpperBound int = (select MAX(ID) from DATA) 

SELECT TOP 1 T.TALLY 
FROM TALLY T 
LEFT OUTER JOIN DATA D on D.ID = T.TALLY 
WHERE T.TALLY >= 0 --Lowest number to check 
AND T.TALLY < @UpperBound --got to be smaller than this 
AND D.ID IS NULL --only want rows that don't match 
ORDER BY T.TALLY ASC 
関連する問題