您还没有真正解释过如何从“序列名称”获取值范围,所以我假设您已经知道那部分,并且可以从日期范围和序列范围开始工作,这可以是为简单起见作为 CTE 提供:
with input (start_date, end_date, start_seq, end_seq, start_at) as (
select date '2021-01-01', date '2021-01-14', 1, 5, 4 from dual
)
select * from input
您使用 Oracle 11g 标记了该问题。如果那是 11gR2,那么您可以使用递归 CTE 从模拟的输入数据生成结果:
with input (start_date, end_date, start_seq, end_seq, start_at) as (
select date '2021-01-01', date '2021-01-14', 1, 5, 4 from dual
),
rcte (dt, seq, end_date, start_seq, end_seq) as (
select start_date, start_at, end_date, start_seq, end_seq
from input
union all
select dt + 1, case when seq = end_seq then start_seq else seq + 1 end,
end_date, start_seq, end_seq
from rcte
where dt < end_date
)
select dt, seq
from rcte
order by dt;
锚成员使用开始日期和开始时间值,并保留以后需要的其他信息。递归成员递增两者,将 seq 值包装在该范围的顶部。给出结果:
DT | SEQ
:-------- | --:
01-JAN-21 | 4
02-JAN-21 | 5
03-JAN-21 | 1
04-JAN-21 | 2
05-JAN-21 | 3
06-JAN-21 | 4
07-JAN-21 | 5
08-JAN-21 | 1
09-JAN-21 | 2
10-JAN-21 | 3
11-JAN-21 | 4
12-JAN-21 | 5
13-JAN-21 | 1
14-JAN-21 | 2
在早期版本中,或者如果您更喜欢它,您可以使用分层查询,它看起来更短,但我认为它不太直观:
with input (start_date, end_date, start_seq, end_seq, start_at) as (
select date '2021-01-01', date '2021-01-14', 1, 5, 4 from dual
)
select start_date + level - 1 as dt,
mod(level - 1 + start_at - start_seq, end_seq - start_seq + 1) + start_seq as seq
from input
connect by level <= end_date - start_date + 1
order by dt;
db<>fiddle 展示了这两种方法。
第二个db<>fiddle 显示不同的序列范围和起点。