| 订阅 | 在线投稿
分享
 
 
 

使用插值在序列中查找遗漏的值

来源:互联网网民  宽屏版  评论
2008-05-31 22:07:57

在有些应用程序中,序列化值的范围能够连续是重要的。当在这个序列新增值的时候,它可能会在序列中优先挑选一个“空的(hole)”或者遗漏的值来填充,而不是取序列最大值之后的下一个值,或者使用一个序号产生器。

例如电话号码、社会安全号码和IP地址都有非常严格的范围限制,所以说最好使用未用的号码来填充。

当数据库中有很多值的时候经常会出现这个问题。遗漏的值明显是不被索引的,所以定位遗漏的数字的最明显的方法是顺序查询所有的值,然后在碰到期望的值的时候将其返回:

REM - table in question is "massive" with a sequence "id"

set serveroutput on;

set timing on;

declare

l_idinteger := null;

begin

for row in (select id from massive order by id) loop

if l_id is null then

l_id := row.id;

else

l_id := l_id + 1;

end if;

exit when l_id != row.id;

end loop;

dbms_output.put_line('lowest missing value = 'l_id);

end;

/

另外一个方法是使用“分而治之”的策略。假如我们已经知道在一个给定的范围内应该有多少个值,并且表上建有索引的话,我们可以相当快地取得实际的记录的条数。假如有一个遗漏的值,实际的记录条数将会比期望的记录的条数少。

我们可以应用相同的方法检测在较小的一半是否有遗漏的值。假如有的话,就继续将其对分。假如没有遗漏的值,我们检测另外一半。最后,我们将要检测的记录集合的大小能够正好只找出遗漏的数据:

下面是这种技术的PL/SQL示例:

set serveroutput on

declare

l_min integer;

l_max integer;

actual_countinteger;

eXPected_countinteger;

halfinteger;

begin

select max(id),min(id),count(*)

into l_max,l_min,actual_count

from massive;

expected_count := l_max - l_min + 1;

if expected_count = actual_count then

dbms_output.put_line('there are no missing values');

end if;

while l_max - l_min = 1 loop

-- try lower half of range

half := trunc(expected_count/2);

expected_count := expected_count - half;

select count(*)

into actual_count

from massive

where id between l_min and l_max - half;

exit when actual_count = 0;

if actual_count = expected_count then

-- missing value must be in upper half

l_min := l_min + half;

else

l_max := l_max - half;

end if;

end loop;

end;

/

对于具有一百万条记录,并且有一个正规索引的表,假如其中漏值只有一个话,有非正式的结果表明第二个脚本的执行速度是第一个的五倍。

 
特别声明:以上内容(如有图片或视频亦包括在内)为网络用户发布,本站仅提供信息存储服务。
 
  在有些应用程序中,序列化值的范围能够连续是重要的。当在这个序列新增值的时候,它可能会在序列中优先挑选一个“空的(hole)”或者遗漏的值来填充,而不是取序列最大值之后的下一个值,或者使用一个序号产生器。 例如电话号码、社会安全号码和IP地址都有非常严格的范围限制,所以说最好使用未用的号码来填充。      当数据库中有很多值的时候经常会出现这个问题。遗漏的值明显是不被索引的,所以定位遗漏的数字的最明显的方法是顺序查询所有的值,然后在碰到期望的值的时候将其返回:      REM - table in question is "massive" with a sequence "id"   set serveroutput on;   set timing on;   declare     l_id    integer := null;   begin     for row in (select id from massive order by id) loop       if l_id is null then         l_id := row.id;       else         l_id := l_id + 1;       end if;       exit when l_id != row.id;     end loop;     dbms_output.put_line('lowest missing value = 'l_id);   end;   /      另外一个方法是使用“分而治之”的策略。假如我们已经知道在一个给定的范围内应该有多少个值,并且表上建有索引的话,我们可以相当快地取得实际的记录的条数。假如有一个遗漏的值,实际的记录条数将会比期望的记录的条数少。      我们可以应用相同的方法检测在较小的一半是否有遗漏的值。假如有的话,就继续将其对分。假如没有遗漏的值,我们检测另外一半。最后,我们将要检测的记录集合的大小能够正好只找出遗漏的数据:      下面是这种技术的PL/SQL示例:      set serveroutput on   declare     l_min        integer;     l_max        integer;     actual_count    integer;     eXPected_count   integer;     half        integer;   begin     select max(id),min(id),count(*)      into l_max,l_min,actual_count      from massive;     expected_count := l_max - l_min + 1;     if expected_count = actual_count then       dbms_output.put_line('there are no missing values');     end if;     while l_max - l_min = 1 loop       -- try lower half of range       half := trunc(expected_count/2);       expected_count := expected_count - half;       select count(*)        into actual_count        from massive        where id between l_min and l_max - half;       exit when actual_count = 0;       if actual_count = expected_count then         -- missing value must be in upper half         l_min := l_min + half;       else         l_max := l_max - half;       end if;     end loop;   end;   /      对于具有一百万条记录,并且有一个正规索引的表,假如其中漏值只有一个话,有非正式的结果表明第二个脚本的执行速度是第一个的五倍。
󰈣󰈤
 
 
 
>>返回首页<<
 
 热帖排行
 
 
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
©2005- 王朝网络 版权所有