【问题标题】:repeat a sequence from a lookup table across a set number of records oracle sql在一组记录中重复查找表中的序列oracle sql
【发布时间】:2021-07-22 03:19:43
【问题描述】:

案例:

用户需要选择特定时期的开始和结束日期,他们还需要选择序列以及他们希望在序列中的哪个位置开始序列周期(序列存储在查找表中。 ..一个存储序列的例子显示在下面的序列查找下的例子中)。

user input parameters:
 start date : 01-jan-2021 
 end date : 14-jan-2021
 sequence_name : 1-5
 start sequence at : 4

用户输入参数后,系统会

列出 2021 年 1 月 1 日至 2021 年 1 月 14 日之间的所有日期 - 示例如下所示,然后它将开始将序列映射到从输入的序列号开始的日期,在这种情况下为 4(如图所示)下面的例子)

当系统到达序列的末尾(在本例中为 5)时,它将从 1 重新开始序列,因为那是查找中序列的开始。

在下面的示例图像中,它显示了结果应该是什么样子。

感谢您的帮助!

我更喜欢用 sql 写,但如果不能用 sql 写,那么 plsql 也可以。

【问题讨论】:

  • 正如我之前所问的那样,请发布文字而不是图片。 sequence_name 在哪里转换为值列表?包括相关表格和样本数据总是有用的。它还可能有助于显示您已经走了多远以及遇到了什么问题。
  • 对不起,伙计,我忘记了如何在堆栈溢出中对表进行隐蔽...所以我发布了图片

标签: sql oracle plsql oracle11g oracle-apex


【解决方案1】:

您还没有真正解释过如何从“序列名称”获取值范围,所以我假设您已经知道那部分,并且可以从日期范围和序列范围开始工作,这可以是为简单起见作为 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 显示不同的序列范围和起点。

【讨论】:

  • 序列名称实际上是'seq1-5'作为名称仅供参考
  • 这足以让我扩展概念谢谢!!!!帮助很大!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多