2014-11-01 28 views
1

查找缺失的序列。表test_number包含每個id的序列。表test_number_min_max包含每個id的最小值和最大值。我們需要爲每個ID找到最小和最大號碼之間的缺失數字。僅查找缺少序號的序列號

我有兩個表

CREATE TABLE test_number(id NUMBER,SEQ NUMBER,text VARCHAR2(5)) ; 
INSERT INTO test_number VALUES(1,1,'AA'); 
INSERT INTO test_number VALUES(1,3,'CC'); 
INSERT INTO test_number VALUES(1,4,'DD'); 
INSERT INTO test_number VALUES(1,5,'EE'); 
INSERT INTO test_number VALUES(1,6,'FF'); 
INSERT INTO test_number VALUES(1,7,'GG'); 
INSERT INTO test_number VALUES(1,8,'HH'); 
INSERT INTO test_number VALUES(1,10,'JJ'); 
INSERT INTO test_number VALUES(2,1,'KK'); 
INSERT INTO test_number VALUES(2,2,'LL'); 
INSERT INTO test_number VALUES(2,3,'MM'); 
INSERT INTO test_number VALUES(2,4,'NN'); 
INSERT INTO test_number VALUES(2,6,'PP'); 
INSERT INTO test_number VALUES(2,7,'QQ'); 
INSERT INTO test_number VALUES(3,1,'TT'); 
INSERT INTO test_number VALUES(3,4,'ZZ'); 
INSERT INTO test_number VALUES(3,5,'XX'); 



create tabel test_number_min_max(id number,mn number,mx number); 
INSERT INTO test_number_min_max VALUES(1,1,12); 
INSERT INTO test_number_min_max VALUES(2,1,9); 
INSERT INTO test_number_min_max VALUES(3,1,5); 

下面的查詢工作在甲骨文,但我想查詢其執行SQL serevr2008。

SELECT r id,rn seq FROM(SELECT ROWNUM rn FROM all_objects WHER ROWNUM <13), 
(SELECT ROWNUM r FROM all_objects 
WHERE ROWNUM <4),test_number_min_max m 
WHERE r=id 
AND rn >= mn 
AND rn <= mx 
AND(r,rn) NOT IN 
(SELECT id,seq FROM test_number) 

請幫幫我。

+0

您可以編輯您的問題,顯示你想要的輸出是什麼? – 2014-11-01 12:39:54

回答

2

您可以通過生成所有可能的數字,然後找到不匹配的數字。以下應Oracle和SQL Server中的工作:

with nums(id, seqnum, mx) as (
     select t.id, t.mn as seqnum, t.mx 
     from test_number_min_max t 
     union all 
     select t.id, t.mn + 1, t.mx 
     from nums 
     where nums.seqnum < t.mx 
    ) 
select nums.id, nums.seqnum 
from nums left outer join 
    test_number tn 
    on tn.id = nums.id and tn.seqnumber = nums.seqnumber 
where tn.id is null; 

如果在最小值和最大值之間超過100個值,那麼你就需要設置最大遞歸。如果性能問題,您可能需要另一種生成數字的方式。這是一種可能(也應該在這兩個數據庫工作):

with nums as (
     select row_number() over (order by id) - 1 as n 
     from test_number 
    ) 
select tnmm.id, tnmm.mn + nums.n as seqnumber 
from test_number_min_max tnmm join 
    nums 
    on tnmm.mn + nums.n <= tnmm.mx left join 
    test_number tn 
    on tn.id = tnmm.id and 
     tn.seqnumber = tnmm.mn + nums.n 
where tn.id is null; 

這假定有足夠的行中​​枚舉test_number_min_max最大範圍(一個合理的假設,但它可能不是真的)。

+0

謝謝Gordon Linoff :) – Sandesh 2014-11-03 06:06:56

1
CREATE TABLE test_number(id INTEGER,SEQ INTEGER,text varchar) ; 
INSERT INTO test_number VALUES 
    (1,1,'AA') 
     , (1,3,'CC') , (1,4,'DD') , (1,5,'EE') , (1,6,'FF') , (1,7,'GG') 
     , (1,8,'HH') , (1,10,'JJ') 
, (2,1,'KK') , (2,2,'LL') , (2,3,'MM') , (2,4,'NN') 
     , (2,6,'PP') , (2,7,'QQ') 
, (3,1,'TT') 
     , (3,4,'ZZ') , (3,5,'XX') 
     ; 

SELECT t1.id AS "Id" 
     , t1.seq+1 AS "Start" 
     , t2.seq-1 AS "Stop" 
     , t2.seq - t1.seq -1 AS "Gapsize" 
FROM test_number t1 
JOIN test_number t2 ON t2.id = t1.id AND t2.seq > t1.seq + 1 
WHERE NOT EXISTS (
     SELECT * FROM test_number nx 
     WHERE nx.id = t1.id 
     AND nx.seq > t1.seq 
     AND nx.seq < t2.seq 
     ); 

結果:

Id | Start | Stop | Gapsize 
----+-------+------+--------- 
    1 |  2 | 2 |  1 
    1 |  9 | 9 |  1 
    2 |  5 | 5 |  1 
    3 |  2 | 3 |  2 
(4 rows)