2009-05-22 43 views
4

比方說,我有如下表有三列:我可以使用SQL來查找下面給出的示例表中的缺失數字嗎?

id | start_block | end_block 
----------------------------- 
01 | 00000000001 | 00000000005 
02 | 00000000006 | 00000000011 
03 | 00000000012 | 00000000018 
04 | 00000000025 | 00000000031 
05 | 00000000032 | 00000000043 

每一行是一個「開始塊」和「結束塊」。如果數據是完美的,每個起始塊將比它之前的結束塊多一個。因此,對於行ID == 02,開始塊是6,而該行的結束塊前5

我需要查詢這些數據(它的幾萬行),並發現任何缺失行。根據我的示例數據,03和04之間應該有一行,其起始塊爲19,結束塊爲24.

我試圖在JSP中構建一個報告以調和這些數據並找到缺少的行。醜陋的方式做,這將是整個記錄拉進一個數組,並在每一行做這樣的事情:

if ((arry(i,1) + 1) != (arry(i+1),1)({ 
    print("Bad Row!\n"); 
} 

但是,我真的希望能夠直接查詢記錄並返回我需要什麼。那可能嗎?如果不是,有人能指出我創建一個存儲過程的正確方向嗎?

+0

我想我應該提到我正在使用Microsoft SQL Server 2005. – messick 2009-05-22 19:10:15

+0

什麼是列數據類型? – 2009-05-22 19:13:52

+0

id是int,另外兩個是字符串。 – messick 2009-05-24 03:42:29

回答

10

當然不會傷害試一試

CREATE TABLE #t (startz INT, zend INT) 
insert into #t (startz, zend) values (1,5) 
insert into #t (startz, zend) values (6,11) 
insert into #t (startz, zend) values (12,18) 
insert into #t (startz, zend) values (25,31) 
insert into #t (startz, zend) values (32,43) 

select * from #t ta 
LEFT OUTER JOIN #t tb ON tb.startz - 1 = ta.zend 
WHERE tb.startz IS NULL 

最後的結果是假陽性。但容易消除。

+0

你是在暗示他爲「成千上萬行」寫這篇文章? – DOK 2009-05-22 20:33:53

0
Select * From Table O 
    Where 
     (Exists 
     (Select * From Table 
      Where End_Block < O.Start_Block) 
     And Not Exists 
     (Select * From Table 
      Where End_Block = O.Start_Block - 1)) 
    Or 
     (Exists 
     (Select * From Table 
      Where Start_Block > O.End_Block) 
     And Not Exists 
     (Select * From Table 
      Where Start_Block = O.End_Block + 1)) 
0
select e1.end_block + 1 as start_hole, 
    (select min(start_block) 
    from extent e3 
    where e3.start_block > e1.end_block) - 1 as end_hole 
from extent e1 
left join extent e2 on e2.start_block = e1.end_block + 1 
where e2.start_block is null 
and e1.end_block <> (select max(end_block) from extent); 

雖然我會說這是一種通過結果TSQL迭代一個合理的候選人:你將不得不掃描整個表(或至少指數上start_blockend_block全部)反正,所以只循環一次,並使用變量來記住最後一個值是目標。

2

你可以嘗試:

SELECT t.ID, t.Start_Block, t.End_Block 
FROM [TableName] t 
JOIN [TableName] t2 ON t.ID = t2.ID+1 
WHERE t.Start_Block - t2.End_Block > 1 
1

這將做到這一點。您可能還想查找重疊的塊。

SELECT 
    T1.end_block + 1 AS start_block, 
    T2.start_block - 1 AS end_block 
FROM 
    dbo.My_Table T1 
INNER JOIN dbo.My_Table T2 ON 
    T2.start_block > T1.end_block 
LEFT OUTER JOIN dbo.My_Table T3 ON 
    T3.start_block > T1.end_block AND 
    T3.start_block < T2.start_block 
WHERE 
    T3.id IS NULL AND 
    T2.start_block <> T1.end_block + 1 
0

這是一個SQL,它實際上告訴你缺少的行!

做得相當快,所以忽略了性能問題:基於

CREATE TABLE #t (startz INT, zend INT) 
insert into #t (startz, zend) values (1,5) 
insert into #t (startz, zend) values (6,11) 
insert into #t (startz, zend) values (12,18) 
insert into #t (startz, zend) values (25,31) 
insert into #t (startz, zend) values (32,43) 
insert into #t (startz, zend) values (45,58) 
insert into #t (startz, zend) values (60,64) 
insert into #t (startz, zend) values (70,98) 


select tab1.zend+1 as MissingStartValue, 
     (select min(startz-1) from #t where startz > tab1.zend+1) as MissingEndValue 
from #t as tab1 where not exists (select 1 from #t as tab2 where tab1.zend + 1 = tab2.startz) 
and (select min(startz-1) from #t where startz > tab1.zend+1) is not null 
0
select * from blocks a 
where not exists (select * from blocks b where b.start_block = a.end_block + 1) 

會給你塊立即缺口之前。你可以看中。讓我們來看看...

select a.end_block, min(b.start_block) 
from blocks a, 
    blocks b 
where not exists (select * from blocks c where c.start_block = a.end_block + 1) 
and b.start_block > a.end_block 
group by a.end_block 

我認爲應該這樣做。

0
SELECT t1.End_Block + 1 as Start_Block, 
     t2.Start_Block - 1 as End_Block, 
    FROM Table as t1, Table as t2 
WHERE t1.ID + 1 = t2.ID 
    AND t1.End_Block + 1 <> T2.Start_Block 

這裏假定表中的ID是連續的。如果它們不是連續的,那麼你必須做一些與Start_Block到End_Block的複雜鏈接來鏈接彼此相鄰的兩個塊。

相關問題