2009-05-22 16 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的复杂链接来链接彼此相邻的两个块。

相关问题