如何在oracle中丢失100s的数字
How to missing numbers by 100s in oracle
我需要在 oracle 的 table 列中找到缺失的数字,其中缺失的数字必须取 100s ,这意味着如果在 2000 和 2099 之间至少找到 1 个数字,则所有缺失的数字2000年到2099年必须归还等等。
这里有一个例子可以阐明我的需要:
create table test1 ( a number(9,0));
insert into test1 values (2001);
insert into test1 values (2002);
insert into test1 values (2004);
insert into test1 values (2105);
insert into test1 values (3006);
insert into test1 values (9410);
commit;
结果必须是2000,2003,2005到2099,2100到2104,2106到2199,3000到3005,3007到3099,9400到9409,9411到9499.
我从这个查询开始,但它显然没有返回我需要的东西:
SELECT Level+(2000-1) FROM dual CONNECT BY LEVEL <= 9999
MINUS SELECT a FROM test1;
我喜欢为此使用标准递归查询。
with nums (a, max_a) as (
select min(a), max(a) from test1
union all
select a + 1, max_a from nums where a < max_a
)
select n.a
from nums n
where not exists (select 1 from test1 t where t.a = n.a)
order by n.a
with
子句取 table 中 a
的最小值和最大值,并生成介于两者之间的所有数字。然后,外部查询过滤那些 table.
中不存在的查询
如果您想生成缺失数字的范围而不是综合列表,您可以改用 window 函数:
select a + 1 start_a, lead_a - 1 end_a
from (
select a, lead(a) over(order by a) lead_a
from test1
) t
where lead_a <> a + 1
编辑:
如果你希望缺失值在数千范围内,那么我们可以稍微调整递归解决方案:
with nums (a, max_a) as (
select distinct floor(a / 100) * 100 a, floor(a / 100) * 100 + 100 from test1
union all
select a + 1, max_a from nums where a < max_a
)
select n.a
from nums n
where not exists (select 1 from test1 t where t.a = n.a)
order by n.a
您可以使用层级查询如下:
SQL> SELECT A FROM (
2 SELECT A + COLUMN_VALUE - 1 AS A
3 FROM ( SELECT DISTINCT TRUNC(A, - 2) A
4 FROM TEST_TABLE) T
5 CROSS JOIN TABLE ( CAST(MULTISET(
6 SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= 100
7 ) AS SYS.ODCINUMBERLIST) ) LEVELS
8 )
9 MINUS
10 SELECT A FROM TEST_TABLE;
A
----------
2000
2003
2005
2006
2007
2008
2009
.....
.....
假设你为范围定义了固定的上下限,那么只需要使用NOT EXISTS
剔除当前查询的结果如
SQL> exec :min_val:=2000
SQL> exec :min_val:=2499
SQL> SELECT *
FROM
(
SELECT level + :min_val - 1 AS nr
FROM dual
CONNECT BY level <= :max_val - :min_val + 1
)
WHERE NOT EXISTS ( SELECT * FROM test1 WHERE a = nr )
ORDER BY nr;
/
我需要在 oracle 的 table 列中找到缺失的数字,其中缺失的数字必须取 100s ,这意味着如果在 2000 和 2099 之间至少找到 1 个数字,则所有缺失的数字2000年到2099年必须归还等等。
这里有一个例子可以阐明我的需要:
create table test1 ( a number(9,0));
insert into test1 values (2001);
insert into test1 values (2002);
insert into test1 values (2004);
insert into test1 values (2105);
insert into test1 values (3006);
insert into test1 values (9410);
commit;
结果必须是2000,2003,2005到2099,2100到2104,2106到2199,3000到3005,3007到3099,9400到9409,9411到9499.
我从这个查询开始,但它显然没有返回我需要的东西:
SELECT Level+(2000-1) FROM dual CONNECT BY LEVEL <= 9999
MINUS SELECT a FROM test1;
我喜欢为此使用标准递归查询。
with nums (a, max_a) as (
select min(a), max(a) from test1
union all
select a + 1, max_a from nums where a < max_a
)
select n.a
from nums n
where not exists (select 1 from test1 t where t.a = n.a)
order by n.a
with
子句取 table 中 a
的最小值和最大值,并生成介于两者之间的所有数字。然后,外部查询过滤那些 table.
如果您想生成缺失数字的范围而不是综合列表,您可以改用 window 函数:
select a + 1 start_a, lead_a - 1 end_a
from (
select a, lead(a) over(order by a) lead_a
from test1
) t
where lead_a <> a + 1
编辑:
如果你希望缺失值在数千范围内,那么我们可以稍微调整递归解决方案:
with nums (a, max_a) as (
select distinct floor(a / 100) * 100 a, floor(a / 100) * 100 + 100 from test1
union all
select a + 1, max_a from nums where a < max_a
)
select n.a
from nums n
where not exists (select 1 from test1 t where t.a = n.a)
order by n.a
您可以使用层级查询如下:
SQL> SELECT A FROM (
2 SELECT A + COLUMN_VALUE - 1 AS A
3 FROM ( SELECT DISTINCT TRUNC(A, - 2) A
4 FROM TEST_TABLE) T
5 CROSS JOIN TABLE ( CAST(MULTISET(
6 SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= 100
7 ) AS SYS.ODCINUMBERLIST) ) LEVELS
8 )
9 MINUS
10 SELECT A FROM TEST_TABLE;
A
----------
2000
2003
2005
2006
2007
2008
2009
.....
.....
假设你为范围定义了固定的上下限,那么只需要使用NOT EXISTS
剔除当前查询的结果如
SQL> exec :min_val:=2000
SQL> exec :min_val:=2499
SQL> SELECT *
FROM
(
SELECT level + :min_val - 1 AS nr
FROM dual
CONNECT BY level <= :max_val - :min_val + 1
)
WHERE NOT EXISTS ( SELECT * FROM test1 WHERE a = nr )
ORDER BY nr;
/