我有一个表part
,其中包含一些演示数据,如下面的Oracle DB中所示:
ID NUMBER DESCRIPTION
1 T00001 test
2 T00002 test
3 T00003 test
4 T00004 test
5 T00008 test
6 SG0001 test
7 SG0002 test
8 SG0003 test
9 SG0004 test
10 SG0006 test
列NUMBER
定义了具有不同预定义前缀和自动增量数后缀的不同类别部分。现在在DB中有一些错过的数字,因此连续性被打破。我想要一个具有完美性能的SQL查询或PL-SQL函数来列出错过的数字:
例如:对于上述演示数据。应返回以下数据:
Category1 start with T: T00005,T00006,T00007
Category1 start with SG: SG0005
有人有想法吗?
答案 0 :(得分:1)
有很多选择。这被称为“群岛和空白”问题。尝试查看以下资源(大多数将在Oracle和SQL服务器中运行。有些可能需要调整):
http://msdn.microsoft.com/en-us/library/aa175780(v=sql.80).aspx
或
答案 1 :(得分:0)
对于SG:
WITH t AS (
SELECT
0 as start_n,
p.a as end_n
FROM (
SELECT MAX(TO_NUMBER(SUBSTR("NUMBER", 3))) a FROM Part p2
WHERE "NUMBER" LIKE 'SG%') p
)
SELECT
'SG' || LPAD(r.cur_num, 4, '0') AS missing_expr
FROM
(SELECT t.start_n + level - 1 AS cur_num FROM t CONNECT BY t.start_n + level - 1 <= t.end_n) r
WHERE
NOT EXISTS(
SELECT * FROM part p WHERE p."NUMBER" = 'SG' || LPAD(r.cur_num, 4, '0')
)
ORDER BY missing_expr ASC;
对于T:
WITH t AS (
SELECT
0 as start_n,
p.a as end_n
FROM (
SELECT MAX(TO_NUMBER(SUBSTR("NUMBER", 2))) a FROM Part p2
WHERE "NUMBER" LIKE 'T%') p
)
SELECT
'T' || LPAD(r.cur_num, 5, '0') AS missing_expr
FROM
(SELECT t.start_n + level - 1 AS cur_num FROM t CONNECT BY t.start_n + level - 1 <= t.end_n) r
WHERE
NOT EXISTS(
SELECT * FROM part p WHERE p.number = 'T' || LPAD(r.cur_num, 5, '0')
)
ORDER BY missing_expr ASC
答案 2 :(得分:0)
对于T使用:
select 'T' || substr('0000' || to_char(r.rn),length(to_char(r.rn)-1))
from (select rownum rn from part
where rownum <= (select max(to_number(substr(p.number,2))) from part p
where p.number like 'T%'
)
) r
where
'T' || substr('0000' || to_char(r.rn),length(to_char(r.rn)-1))
not in (select p.number from part p where p.number like 'T%');
供SG使用:
select 'SG' || substr('000' || to_char(r.rn),length(to_char(r.rn)-1))
from (select rownum rn from part
where rownum <= (select max(to_number(substr(p.number,3))) from part p
where p.number like 'SG%'
)
) r
where
'SG' || substr('000' || to_char(r.rn),length(to_char(r.rn)-1))
not in (select p.number from part p where p.number like 'SG%');
有几点需要注意:
1)我正在使用表PART获取rownum值。如果有足够的行,则可以使用任何表。如果使用此方法,请确保使用足够大的表来提取所需的值范围。 USER_OBJECTS也可以正常工作。 PART可能没有足够的值来使用。
2)似乎NUMBER作为列名会导致您遇到问题。这是Oracle中的保留字。在我的测试中,我使用了不同的列名。