如何在 Oracle 中找到两个大小范围之间缺失的大小范围?
How to find the missing size range between two size ranges in Oracle?
我想验证两个尺寸范围之间缺失的尺寸范围。例如,现在我有一个名为 AQL 的 table,它具有以下列:
ID TYPE SIZE_FROM SIZE_TO
-- ---------- --------- -------
68 NORMAL 2 150
69 NORMAL 501 1200
70 REDUCED 1201 3200
71 REDUCED 151 500
我需要找出缺失的范围是:
TYPE SIZE_FROM SIZE_TO
--------- --------- -------
NORMAL 151 500
REDUCED 2 150
REDUCED 501 1200
我已经处理了重叠,那么我应该如何处理select以下缺失的范围?
对于示例数据,看看这是否有帮助(阅读代码中的注释):
SQL> with
2 aql (id, type, size_from, size_to) as
3 -- Your current data
4 (select 68, 'NORMAL' , 2, 150 from dual union all
5 select 69, 'NORMAL' , 501, 1200 from dual union all
6 select 70, 'REDUCED', 1201, 3200 from dual union all
7 select 71, 'REDUCED', 151, 500 from dual
8 ),
9 existing_sizes as
10 -- list all existing sizes, one-by-one, per type
11 (select type, size_from + column_value - 1 csize
12 from aql cross join table(cast(multiset(select level from dual
13 connect by level <= size_to - size_from + 1
14 ) as sys.odcinumberlist))
15 ),
16 minmax as
17 -- find MIN and MAX size valze per type - will be used in ALLSIZES CTE
18 (select type, min(size_from) size_from, max(size_to) size_to
19 from aql
20 group by type
21 ),
22 allsizes as
23 -- list all sizes (per type) between MIN and MAX value
24 (select type, size_from + column_value - 1 csize
25 from minmax cross join table(cast(multiset(select level from dual
26 connect by level <= size_to - size_from + 1
27 ) as sys.odcinumberlist))
28 ),
29 missing_sizes as
30 -- missing sizes can be found with MINUS set operator
31 (select a.type, a.csize from allsizes a
32 minus
33 select e.type, e.csize from existing_sizes e
34 )
35 -- the final result
36 select type, min(csize) size_from, max(csize) size_to
37 from missing_sizes
38 group by type;
TYPE SIZE_FROM SIZE_TO
------- ---------- ----------
NORMAL 151 500
REDUCED 501 1200
SQL>
但是,如果涉及更多间隙,这将失败(但这不是您的样本数据所暗示的)。
select ... from dual connect by level <=
语法可用于在每种类型的极值之间生成行,并且在每个范围(size_from & size_to ) 通过使用上述语法再次针对每种类型:
with aql2 as
(
select type, min(size_from) as size_from , max(size_to) as size_to
from aql
group by type
)
select a2.type, min(a2.lvl) as size_from, max(a2.lvl) as size_to
from (select a2.type, a2.size_from + level - 1 as lvl
from aql2 a2
cross join dual d
connect by level <= a2.size_to - a2.size_from + 1
and prior a2.type =a2.type
and prior sys_guid() is not null) a2
left join (select distinct a.type, a.size_from + level - 1 as lvl
from aql a
cross join dual d
connect by level <= a.size_to - a.size_from + 1
group by a.type, a.size_from + level - 1) a
on a2.type = a.type
and a2.lvl = a.lvl
where a.lvl is null
group by a2.type
我想验证两个尺寸范围之间缺失的尺寸范围。例如,现在我有一个名为 AQL 的 table,它具有以下列:
ID TYPE SIZE_FROM SIZE_TO
-- ---------- --------- -------
68 NORMAL 2 150
69 NORMAL 501 1200
70 REDUCED 1201 3200
71 REDUCED 151 500
我需要找出缺失的范围是:
TYPE SIZE_FROM SIZE_TO
--------- --------- -------
NORMAL 151 500
REDUCED 2 150
REDUCED 501 1200
我已经处理了重叠,那么我应该如何处理select以下缺失的范围?
对于示例数据,看看这是否有帮助(阅读代码中的注释):
SQL> with
2 aql (id, type, size_from, size_to) as
3 -- Your current data
4 (select 68, 'NORMAL' , 2, 150 from dual union all
5 select 69, 'NORMAL' , 501, 1200 from dual union all
6 select 70, 'REDUCED', 1201, 3200 from dual union all
7 select 71, 'REDUCED', 151, 500 from dual
8 ),
9 existing_sizes as
10 -- list all existing sizes, one-by-one, per type
11 (select type, size_from + column_value - 1 csize
12 from aql cross join table(cast(multiset(select level from dual
13 connect by level <= size_to - size_from + 1
14 ) as sys.odcinumberlist))
15 ),
16 minmax as
17 -- find MIN and MAX size valze per type - will be used in ALLSIZES CTE
18 (select type, min(size_from) size_from, max(size_to) size_to
19 from aql
20 group by type
21 ),
22 allsizes as
23 -- list all sizes (per type) between MIN and MAX value
24 (select type, size_from + column_value - 1 csize
25 from minmax cross join table(cast(multiset(select level from dual
26 connect by level <= size_to - size_from + 1
27 ) as sys.odcinumberlist))
28 ),
29 missing_sizes as
30 -- missing sizes can be found with MINUS set operator
31 (select a.type, a.csize from allsizes a
32 minus
33 select e.type, e.csize from existing_sizes e
34 )
35 -- the final result
36 select type, min(csize) size_from, max(csize) size_to
37 from missing_sizes
38 group by type;
TYPE SIZE_FROM SIZE_TO
------- ---------- ----------
NORMAL 151 500
REDUCED 501 1200
SQL>
但是,如果涉及更多间隙,这将失败(但这不是您的样本数据所暗示的)。
select ... from dual connect by level <=
语法可用于在每种类型的极值之间生成行,并且在每个范围(size_from & size_to ) 通过使用上述语法再次针对每种类型:
with aql2 as
(
select type, min(size_from) as size_from , max(size_to) as size_to
from aql
group by type
)
select a2.type, min(a2.lvl) as size_from, max(a2.lvl) as size_to
from (select a2.type, a2.size_from + level - 1 as lvl
from aql2 a2
cross join dual d
connect by level <= a2.size_to - a2.size_from + 1
and prior a2.type =a2.type
and prior sys_guid() is not null) a2
left join (select distinct a.type, a.size_from + level - 1 as lvl
from aql a
cross join dual d
connect by level <= a.size_to - a.size_from + 1
group by a.type, a.size_from + level - 1) a
on a2.type = a.type
and a2.lvl = a.lvl
where a.lvl is null
group by a2.type