我在做一个项目,创建一所大学承认系统; 该技术是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?