假设我的下表有三列:
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 :(得分: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
最后的结果是假阳性。但很容易消除。
答案 1 :(得分: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
答案 2 :(得分: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
答案 3 :(得分: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 ))
答案 4 :(得分: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_block
和{{1的整个索引无论如何,所以只循环一次并使用变量来记住最后一个值是目标。
答案 5 :(得分: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
答案 6 :(得分: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
我认为应该这样做。
答案 7 :(得分: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进行一些复杂的链接,以链接彼此相邻的两个块。