如何从一系列数字,检查任何缺失的号码吗?(How to check any missing numb

2019-06-25 10:08发布

我在做一个项目,创建一所大学承认系统; 该技术是Java和Oracle。

在该表中的一个,生成的预序列号被存储。 后来,对这些序列号,申请人的表格数据将被输入。 我的要求是,当完成录入过程中,我将不得不产生大量明智的报告。 如果饲养过程中预先生成的序列号的任何序列号失踪。

例如,假设在一个表中,该序列号是7001,7002,7004,7005,7006,7010从上面的一系列很显然,从7001到7010的数字失踪是7003,7007,7008和7009

有没有在Oracle中,找出这些数字,或者如果任何存储过程可以实现自己的目的,那么请提出的算法任何DBMS的功能。

我能找到一些Java技术,但速度我想找到的Oracle解决方案。

Answer 1:

没有硬编码9 A液:

select min_a - 1 + level
     from ( select min(a) min_a
                 , max(a) max_a
              from test1
          )
  connect by level <= max_a - min_a + 1
    minus
   select a
     from test1

结果:

MIN_A-1+LEVEL
-------------
         7003
         7007
         7008
         7009

4 rows selected.


Answer 2:

试试这个:

SELECT t1.SequenceNumber + 1 AS "From",
       MIN(t2.SequenceNumber) - 1 AS "To"
FROM MyTable t1
JOIN MyTable t2 ON t1.SequenceNumber < t2.SequenceNumber 
GROUP BY t1.SequenceNumber
HAVING t1.SequenceNumber + 1 < MIN(t2.SequenceNumber)

下面是序列7001,7002,7004,7005,7006,7010结果:

From  To
7003  7003
7007  7009


Answer 3:

这部作品的Postgres> = 8.4。 稍作修改的CTE语法就可以作出对甲骨文和微软工作了。

-- EXPLAIN ANALYZE
WITH missing AS (
    WITH RECURSIVE fullhouse AS (
        SELECT MIN(num)+1 as num
        FROM numbers n0
        UNION ALL SELECT 1+ fh0.num AS num
        FROM fullhouse fh0
        WHERE EXISTS (
                SELECT * FROM numbers ex
                WHERE ex.num > fh0.num
                )
        )
        SELECT * FROM fullhouse fh1
        EXCEPT ( SELECT num FROM numbers nx)
        )
SELECT * FROM missing;


Answer 4:

一个简单的方法,让您为您的方案的答案是这样的:

create table test1 ( a number(9,0));

insert into test1 values (7001);
insert into test1 values (7002);
insert into test1 values (7004);
insert into test1 values (7005);
insert into test1 values (7006);
insert into test1 values (7010);
commit;

select n.n from (select ROWNUM + 7001 as n from dual connect by level <= 9) n 
   left join test1 t on n.n = t.a where t.a is null;

选择会给你从你的例子答案。 这仅是有道理的,如果你事先知道在该范围内的号码和幅度不宜过大。 第一个数字必须在被所述偏移ROWNUM部分和序列的长度是限制在电平connect by部分。



Answer 5:

我会建议connect by level的斯特凡做了 ,但是,你不能在此声明,这意味着它是不是真的适合你,你需要知道使用子查询什么的最大值和最小值您的序列。

我建议一个管道内衬表函数可能会产生你需要做的加入了数字的最好方式。 为了这个工作你需要一个对象在数据库中的值返回:

create or replace type t_num_array as table of number;

然后函数:

create or replace function generate_serial_nos return t_num_array pipelined is

   l_first number;
   l_last number;

begin

   select min(serial_no), max_serial_no)
     into l_first, l_last 
     from my_table
          ;

   for i in l_first .. l_last loop
      pipe row(i);
   end loop;

   return;

end generate_serial_nos;
/

使用此功能,以下将返回序列号的列表,最小值和最大值之间。

select * from table(generate_serial_nos);

这意味着,您的查询,找出哪些序列号丢失变为:

select serial_no
  from ( select * 
           from table(generate_serial_nos) 
                ) generator 
  left outer join my_table actual
    on generator.column_value = actual.serial_no
 where actual.serial_no is null


Answer 6:

这个工作,但选择的第一序列(开始值),因为它不具备的前身。 经测试,在SQL Server,但应在甲骨文工作

SELECT
    s.sequence  FROM seqs s
WHERE
    s.sequence - (SELECT sequence FROM seqs WHERE sequence = s.sequence-1) IS NULL

下面是测试结果

  Table
  -------------
  7000
  7001
  7004
  7005
  7007
  7008

  Result
  ----------
  7000
  7004
  7007

为了得到未分配的序列,只是做value[i] - 1其中,i是大于第一行例如(7004 - 1 = 7003 and 7007 - 1 = 7006)其是可获得的序列

我想你可以改善这种简单的查询



Answer 7:

这里有一个解决方案:

  • 凭借Oracle的LAG功能
  • 不需要完整序列的知识(但因此不会检测是否在序列的第一个或最后一个数字被遗漏)
  • 列出周边号码的丢失列表中的值
  • 列出的数字为连续组的失踪名单(也许是便于报告)
  • 可悲的失败为丢失号码的非常大名单,由于LISTAGG限制

SQL:

WITH MentionedValues /*this would just be your actual table, only defined here to provide data for this example */
        AS (SELECT *
              FROM (    SELECT LEVEL + 7000 seqnum
                          FROM DUAL
                    CONNECT BY LEVEL <= 10000)
             WHERE seqnum NOT IN (7003,7007,7008,7009)--omit those four per example
                                       ),
     Ranges /*identifies all ranges between adjacent rows*/
        AS (SELECT seqnum AS seqnum_curr,
                   LAG (seqnum, 1) OVER (ORDER BY seqnum) AS seqnum_prev,
                   seqnum - (LAG (seqnum, 1) OVER (ORDER BY seqnum)) AS diff
              FROM MentionedValues)
SELECT Ranges.*,
       (    SELECT LISTAGG (Ranges.seqnum_prev + LEVEL, ',') WITHIN GROUP (ORDER BY 1)
              FROM DUAL
        CONNECT BY LEVEL < Ranges.diff) "MissingValues" /*count from lower seqnum+1 up to lower_seqnum+(diff-1)*/
  FROM Ranges
 WHERE diff != 1 /*ignore when diff=1 because that means the numers are sequential without skipping any*/
;

输出:

SEQNUM_CURR SEQNUM_PREV DIFF MissingValues
7004        7002        2    "7003" 
7010        7006        4    "7007,7008,7009"                  


Answer 8:

 SELECT ROWNUM "Missing_Numbers" FROM dual CONNECT BY LEVEL <= (SELECT MAX(a) FROM test1)
 MINUS
 SELECT a FROM test1 ;


Answer 9:

 select    A.ID + 1 As ID
From [Missing] As A
Where A.ID + 1 Not IN (Select ID from [Missing])
And A.ID < n

Data: ID
1
2
5
7
Result: ID
3
4
6


文章来源: How to check any missing number from a series of numbers?