从给定模式 Oracle 构造模式
Construct pattern from a given pattern Oracle
我想根据存储在 view.Generate 未来 1 年模式中的给定模式构建系列。我尝试使用 row_number
和 connect by
和 Lead
,但无法构建。
pattern id 可以是任意随机数,不按顺序排列。
每个循环跳过接下来的两个 id。
换句话说,从视图中出现的模式中,我必须查看哪两个模式 ID 丢失或没有日期,然后在下一次迭代中,这些模式 ID 将有日期,接下来的两个按顺序排列不会have.And等等..
我不需要显示日期为 NULL 的那些,这也很好。
我只是为了让它易于理解。
我目前使用的是 Oracle 12.1
预期输出
等等...
为此table(table名称是“patern”):
PATERN_ID DATUM
--------------------
3
4 10/11/2022
5 10/12/2022
6 10/13/2022
7 10/14/2022
10 10/15/2022
11
此 plsql 代码:
declare
idx number:=1;
v_min_date date;
v_end_year date;
v_date_diff number;
type t_index is table of number index by PLS_INTEGER;
type t_patern_row is table of patern%rowtype index by PLS_INTEGER;
index_null t_index;
v_patern_row t_patern_row;
num_of_repeat number;
begin
select min(datum) into v_min_date from patern;
v_end_year:= trunc((v_min_date + 366),'yyyy');
select (to_date(v_end_year,'mm/dd/yyyy') - to_date(v_min_date,'mm/dd/yyyy'))
into v_date_diff from dual;
select * bulk collect into v_patern_row from patern order by patern_id;
num_of_repeat:=ceil(v_date_diff/(v_patern_row.count-2));
for i in 1..num_of_repeat loop
for j in v_patern_row.first..v_patern_row.last loop
if v_patern_row(j).datum is null then
dbms_output.put_line(v_patern_row(j).patern_id||' '||v_patern_row(j).datum);
else
dbms_output.put_line(v_patern_row(j).patern_id||' '||v_min_date);
v_min_date:=v_min_date +1;
end if;
end loop;
for r in v_patern_row.first..v_patern_row.last loop
v_patern_row(r).datum:=v_patern_row(r).datum+4;
if v_patern_row(r).datum is null then
index_null(idx):=r;
idx:=idx+1;
v_patern_row(r).datum:=to_date('11.11.1111','dd.mm.yyyy');
end if;
end loop;
if index_null(1)=v_patern_row.count then
index_null(1):=v_patern_row.first+1;
else
index_null(1):=index_null(1)+2;
if index_null(1)>v_patern_row.count then
index_null(1):= index_null(1)-v_patern_row.count;
end if;
end if;
if index_null(2)=v_patern_row.count then
index_null(2):=v_patern_row.first+1;
else
index_null(2):=index_null(2)+2;
if index_null(2)>v_patern_row.count then
index_null(2):= index_null(2)-v_patern_row.count;
end if;
end if;
v_patern_row(index_null(1)).datum:=null;
v_patern_row(index_null(2)).datum:=null;
end loop;
end;
给出这个结果:
3
4 10/11/2022
5 10/12/2022
6 10/13/2022
7 10/14/2022
10 10/15/2022
11
3 10/16/2022
4
5
6 10/17/2022
7 10/18/2022
10 10/19/2022
11 10/20/2022
3 10/21/2022
4 10/22/2022
5 10/23/2022
6
7
10 10/24/2022
11 10/25/2022
3 10/26/2022
4 10/27/2022
5 10/28/2022
6 10/29/2022
7 10/30/2022
10
11
3
4
5 10/31/2022
6 11/01/2022
7 11/02/2022
10 11/03/2022
11 11/04/2022
3 11/05/2022
4 11/06/2022
5
6
7 11/07/2022
10 11/08/2022
11 11/09/2022
3 11/10/2022
4 11/11/2022
5 11/12/2022
6 11/13/2022
7
10
11 11/14/2022
3
4 11/15/2022
5 11/16/2022
6 11/17/2022
7 11/18/2022
10 11/19/2022
11
3 11/20/2022
4
5
6 11/21/2022
7 11/22/2022
10 11/23/2022
11 11/24/2022
3 11/25/2022
4 11/26/2022
5 11/27/2022
6
7
10 11/28/2022
11 11/29/2022
3 11/30/2022
4 12/01/2022
5 12/02/2022
6 12/03/2022
7 12/04/2022
10
11
3
4
5 12/05/2022
6 12/06/2022
7 12/07/2022
10 12/08/2022
11 12/09/2022
3 12/10/2022
4 12/11/2022
5
6
7 12/12/2022
10 12/13/2022
11 12/14/2022
3 12/15/2022
4 12/16/2022
5 12/17/2022
6 12/18/2022
7
10
11 12/19/2022
3
4 12/20/2022
5 12/21/2022
6 12/22/2022
7 12/23/2022
10 12/24/2022
11
3 12/25/2022
4
5
6 12/26/2022
7 12/27/2022
10 12/28/2022
11 12/29/2022
3 12/30/2022
4 12/31/2022
5 01/01/2023
6
7
10 01/02/2023
11 01/03/2023
PL/SQL procedure successfully completed.
它仍然适用于这种模式:
PATERN_ID DATUM
--------------------
3 10/12/2022
4
5
6 10/13/2022
7 10/14/2022
10 10/15/2022
11 10/16/2022
结果如下:
3 10/12/2022
4
5
6 10/13/2022
7 10/14/2022
10 10/15/2022
11 10/16/2022
3 10/17/2022
4 10/18/2022
5 10/19/2022
6
7
10 10/20/2022
11 10/21/2022
3 10/22/2022
4 10/23/2022
5 10/24/2022
6 10/25/2022
7 10/26/2022
10
11
3
4
5 10/27/2022
6 10/28/2022
7 10/29/2022
10 10/30/2022
11 10/31/2022
3 11/01/2022
4 11/02/2022
5
6
7 11/03/2022
10 11/04/2022
11 11/05/2022
3 11/06/2022
4 11/07/2022
5 11/08/2022
6 11/09/2022
7
10
11 11/10/2022
3
4 11/11/2022
5 11/12/2022
6 11/13/2022
7 11/14/2022
10 11/15/2022
11
3 11/16/2022
4
5
6 11/17/2022
7 11/18/2022
10 11/19/2022
11 11/20/2022
3 11/21/2022
4 11/22/2022
5 11/23/2022
6
7
10 11/24/2022
11 11/25/2022
3 11/26/2022
4 11/27/2022
5 11/28/2022
6 11/29/2022
7 11/30/2022
10
11
3
4
5 12/01/2022
6 12/02/2022
7 12/03/2022
10 12/04/2022
11 12/05/2022
3 12/06/2022
4 12/07/2022
5
6
7 12/08/2022
10 12/09/2022
11 12/10/2022
3 12/11/2022
4 12/12/2022
5 12/13/2022
6 12/14/2022
7
10
11 12/15/2022
3
4 12/16/2022
5 12/17/2022
6 12/18/2022
7 12/19/2022
10 12/20/2022
11
3 12/21/2022
4
5
6 12/22/2022
7 12/23/2022
10 12/24/2022
11 12/25/2022
3 12/26/2022
4 12/27/2022
5 12/28/2022
6
7
10 12/29/2022
11 12/30/2022
3 12/31/2022
4 01/01/2023
5 01/02/2023
6 01/03/2023
7 01/04/2023
10
11
结果从 table 模式的最小(日期)到那年年底。
该代码仅适用于模式中的 2 个空值。
在 dbms_output.put_line() 过程中,您可以插入另一个 table。
这是我针对相同问题的 sql 解决方案,
它非常复杂,但我不知道更好:)
with
test as (
select rownum abc,(minu + level - 1) date_list from
(select min(datum) minu from patern) min_datum
connect by level <=
trunc((minu+365),'yyyy')+(((trunc((minu+365),'yyyy')-minu)/30)*9)- minu ---> Reduce this number if date goes beyond 31.12.
),
test2 as (
select rownum abc,patern_id from patern
cross join
(select rownum n from dual
connect by level<=
(select (trunc((min(datum)+365),'yyyy')- min(datum)) from patern))
),
test3 as (
select ((null_row + (level*9))-10) first_null_row, (null_row + (level*9))-9 second_null_row from (
select max(abc) null_row from
(select rownum abc, datum from patern)
where datum is null)
connect by level <=
(select (trunc((min(datum)+365),'yyyy')- min(datum)) from patern)
),
test4 as(
select rownum abc, a.date_list, b.patern_id
from test a,test2 b
where a.abc=b.abc
),
test5 as(
select
rownum abc,
case
when a.abc in (select first_null_row from test3) or
a.abc in (select second_null_row from test3) then null
else a.date_list
end datum,
patern_id
from test4 a
),
test6 as(
select rownum abc, patern_id from test5 where datum is not null
)
select b.patern_id, a.date_list
from test4 a,test6 b
where
a.abc=b.abc
结果:
PATERN_ID | DATE_LIST
---------------------
3 11.10.2022
4 12.10.2022
7 13.10.2022
10 14.10.2022
11 15.10.2022
3 16.10.2022
4 17.10.2022
5 18.10.2022
6 19.10.2022
11 20.10.2022
3 21.10.2022
4 22.10.2022
5 23.10.2022
6 24.10.2022
7 25.10.2022
10 26.10.2022
4 27.10.2022
5 28.10.2022
6 29.10.2022
7 30.10.2022
10 31.10.2022
11 01.11.2022
3 02.11.2022
6 03.11.2022
7 04.11.2022
10 05.11.2022
11 06.11.2022
3 07.11.2022
4 08.11.2022
5 09.11.2022
10 10.11.2022
11 11.11.2022
3 12.11.2022
4 13.11.2022
5 14.11.2022
6 15.11.2022
7 16.11.2022
3 17.11.2022
4 18.11.2022
5 19.11.2022
6 20.11.2022
7 21.11.2022
10 22.11.2022
11 23.11.2022
5 24.11.2022
6 25.11.2022
7 26.11.2022
10 27.11.2022
11 28.11.2022
3 29.11.2022
4 30.11.2022
7 01.12.2022
10 02.12.2022
11 03.12.2022
3 04.12.2022
4 05.12.2022
5 06.12.2022
6 07.12.2022
11 08.12.2022
3 09.12.2022
4 10.12.2022
5 11.12.2022
6 12.12.2022
7 13.12.2022
10 14.12.2022
4 15.12.2022
5 16.12.2022
6 17.12.2022
7 18.12.2022
10 19.12.2022
11 20.12.2022
3 21.12.2022
6 22.12.2022
7 23.12.2022
10 24.12.2022
11 25.12.2022
3 26.12.2022
4 27.12.2022
5 28.12.2022
10 29.12.2022
11 30.12.2022
3 31.12.2022
PS。它不像我发布的 plsql 代码那样灵活,它不会对每个 patern_id 超过 2 个空值起作用,有时它会超出 31.12 一点点。模式年的(我标记了规范日期的代码行,如果它超过 31.12。只需减少数字一点)
我想根据存储在 view.Generate 未来 1 年模式中的给定模式构建系列。我尝试使用 row_number
和 connect by
和 Lead
,但无法构建。
pattern id 可以是任意随机数,不按顺序排列。
每个循环跳过接下来的两个 id。
换句话说,从视图中出现的模式中,我必须查看哪两个模式 ID 丢失或没有日期,然后在下一次迭代中,这些模式 ID 将有日期,接下来的两个按顺序排列不会have.And等等.. 我不需要显示日期为 NULL 的那些,这也很好。 我只是为了让它易于理解。
我目前使用的是 Oracle 12.1
预期输出
等等...
为此table(table名称是“patern”):
PATERN_ID DATUM
--------------------
3
4 10/11/2022
5 10/12/2022
6 10/13/2022
7 10/14/2022
10 10/15/2022
11
此 plsql 代码:
declare
idx number:=1;
v_min_date date;
v_end_year date;
v_date_diff number;
type t_index is table of number index by PLS_INTEGER;
type t_patern_row is table of patern%rowtype index by PLS_INTEGER;
index_null t_index;
v_patern_row t_patern_row;
num_of_repeat number;
begin
select min(datum) into v_min_date from patern;
v_end_year:= trunc((v_min_date + 366),'yyyy');
select (to_date(v_end_year,'mm/dd/yyyy') - to_date(v_min_date,'mm/dd/yyyy'))
into v_date_diff from dual;
select * bulk collect into v_patern_row from patern order by patern_id;
num_of_repeat:=ceil(v_date_diff/(v_patern_row.count-2));
for i in 1..num_of_repeat loop
for j in v_patern_row.first..v_patern_row.last loop
if v_patern_row(j).datum is null then
dbms_output.put_line(v_patern_row(j).patern_id||' '||v_patern_row(j).datum);
else
dbms_output.put_line(v_patern_row(j).patern_id||' '||v_min_date);
v_min_date:=v_min_date +1;
end if;
end loop;
for r in v_patern_row.first..v_patern_row.last loop
v_patern_row(r).datum:=v_patern_row(r).datum+4;
if v_patern_row(r).datum is null then
index_null(idx):=r;
idx:=idx+1;
v_patern_row(r).datum:=to_date('11.11.1111','dd.mm.yyyy');
end if;
end loop;
if index_null(1)=v_patern_row.count then
index_null(1):=v_patern_row.first+1;
else
index_null(1):=index_null(1)+2;
if index_null(1)>v_patern_row.count then
index_null(1):= index_null(1)-v_patern_row.count;
end if;
end if;
if index_null(2)=v_patern_row.count then
index_null(2):=v_patern_row.first+1;
else
index_null(2):=index_null(2)+2;
if index_null(2)>v_patern_row.count then
index_null(2):= index_null(2)-v_patern_row.count;
end if;
end if;
v_patern_row(index_null(1)).datum:=null;
v_patern_row(index_null(2)).datum:=null;
end loop;
end;
给出这个结果:
3
4 10/11/2022
5 10/12/2022
6 10/13/2022
7 10/14/2022
10 10/15/2022
11
3 10/16/2022
4
5
6 10/17/2022
7 10/18/2022
10 10/19/2022
11 10/20/2022
3 10/21/2022
4 10/22/2022
5 10/23/2022
6
7
10 10/24/2022
11 10/25/2022
3 10/26/2022
4 10/27/2022
5 10/28/2022
6 10/29/2022
7 10/30/2022
10
11
3
4
5 10/31/2022
6 11/01/2022
7 11/02/2022
10 11/03/2022
11 11/04/2022
3 11/05/2022
4 11/06/2022
5
6
7 11/07/2022
10 11/08/2022
11 11/09/2022
3 11/10/2022
4 11/11/2022
5 11/12/2022
6 11/13/2022
7
10
11 11/14/2022
3
4 11/15/2022
5 11/16/2022
6 11/17/2022
7 11/18/2022
10 11/19/2022
11
3 11/20/2022
4
5
6 11/21/2022
7 11/22/2022
10 11/23/2022
11 11/24/2022
3 11/25/2022
4 11/26/2022
5 11/27/2022
6
7
10 11/28/2022
11 11/29/2022
3 11/30/2022
4 12/01/2022
5 12/02/2022
6 12/03/2022
7 12/04/2022
10
11
3
4
5 12/05/2022
6 12/06/2022
7 12/07/2022
10 12/08/2022
11 12/09/2022
3 12/10/2022
4 12/11/2022
5
6
7 12/12/2022
10 12/13/2022
11 12/14/2022
3 12/15/2022
4 12/16/2022
5 12/17/2022
6 12/18/2022
7
10
11 12/19/2022
3
4 12/20/2022
5 12/21/2022
6 12/22/2022
7 12/23/2022
10 12/24/2022
11
3 12/25/2022
4
5
6 12/26/2022
7 12/27/2022
10 12/28/2022
11 12/29/2022
3 12/30/2022
4 12/31/2022
5 01/01/2023
6
7
10 01/02/2023
11 01/03/2023
PL/SQL procedure successfully completed.
它仍然适用于这种模式:
PATERN_ID DATUM
--------------------
3 10/12/2022
4
5
6 10/13/2022
7 10/14/2022
10 10/15/2022
11 10/16/2022
结果如下:
3 10/12/2022
4
5
6 10/13/2022
7 10/14/2022
10 10/15/2022
11 10/16/2022
3 10/17/2022
4 10/18/2022
5 10/19/2022
6
7
10 10/20/2022
11 10/21/2022
3 10/22/2022
4 10/23/2022
5 10/24/2022
6 10/25/2022
7 10/26/2022
10
11
3
4
5 10/27/2022
6 10/28/2022
7 10/29/2022
10 10/30/2022
11 10/31/2022
3 11/01/2022
4 11/02/2022
5
6
7 11/03/2022
10 11/04/2022
11 11/05/2022
3 11/06/2022
4 11/07/2022
5 11/08/2022
6 11/09/2022
7
10
11 11/10/2022
3
4 11/11/2022
5 11/12/2022
6 11/13/2022
7 11/14/2022
10 11/15/2022
11
3 11/16/2022
4
5
6 11/17/2022
7 11/18/2022
10 11/19/2022
11 11/20/2022
3 11/21/2022
4 11/22/2022
5 11/23/2022
6
7
10 11/24/2022
11 11/25/2022
3 11/26/2022
4 11/27/2022
5 11/28/2022
6 11/29/2022
7 11/30/2022
10
11
3
4
5 12/01/2022
6 12/02/2022
7 12/03/2022
10 12/04/2022
11 12/05/2022
3 12/06/2022
4 12/07/2022
5
6
7 12/08/2022
10 12/09/2022
11 12/10/2022
3 12/11/2022
4 12/12/2022
5 12/13/2022
6 12/14/2022
7
10
11 12/15/2022
3
4 12/16/2022
5 12/17/2022
6 12/18/2022
7 12/19/2022
10 12/20/2022
11
3 12/21/2022
4
5
6 12/22/2022
7 12/23/2022
10 12/24/2022
11 12/25/2022
3 12/26/2022
4 12/27/2022
5 12/28/2022
6
7
10 12/29/2022
11 12/30/2022
3 12/31/2022
4 01/01/2023
5 01/02/2023
6 01/03/2023
7 01/04/2023
10
11
结果从 table 模式的最小(日期)到那年年底。
该代码仅适用于模式中的 2 个空值。
在 dbms_output.put_line() 过程中,您可以插入另一个 table。
这是我针对相同问题的 sql 解决方案, 它非常复杂,但我不知道更好:)
with
test as (
select rownum abc,(minu + level - 1) date_list from
(select min(datum) minu from patern) min_datum
connect by level <=
trunc((minu+365),'yyyy')+(((trunc((minu+365),'yyyy')-minu)/30)*9)- minu ---> Reduce this number if date goes beyond 31.12.
),
test2 as (
select rownum abc,patern_id from patern
cross join
(select rownum n from dual
connect by level<=
(select (trunc((min(datum)+365),'yyyy')- min(datum)) from patern))
),
test3 as (
select ((null_row + (level*9))-10) first_null_row, (null_row + (level*9))-9 second_null_row from (
select max(abc) null_row from
(select rownum abc, datum from patern)
where datum is null)
connect by level <=
(select (trunc((min(datum)+365),'yyyy')- min(datum)) from patern)
),
test4 as(
select rownum abc, a.date_list, b.patern_id
from test a,test2 b
where a.abc=b.abc
),
test5 as(
select
rownum abc,
case
when a.abc in (select first_null_row from test3) or
a.abc in (select second_null_row from test3) then null
else a.date_list
end datum,
patern_id
from test4 a
),
test6 as(
select rownum abc, patern_id from test5 where datum is not null
)
select b.patern_id, a.date_list
from test4 a,test6 b
where
a.abc=b.abc
结果:
PATERN_ID | DATE_LIST
---------------------
3 11.10.2022
4 12.10.2022
7 13.10.2022
10 14.10.2022
11 15.10.2022
3 16.10.2022
4 17.10.2022
5 18.10.2022
6 19.10.2022
11 20.10.2022
3 21.10.2022
4 22.10.2022
5 23.10.2022
6 24.10.2022
7 25.10.2022
10 26.10.2022
4 27.10.2022
5 28.10.2022
6 29.10.2022
7 30.10.2022
10 31.10.2022
11 01.11.2022
3 02.11.2022
6 03.11.2022
7 04.11.2022
10 05.11.2022
11 06.11.2022
3 07.11.2022
4 08.11.2022
5 09.11.2022
10 10.11.2022
11 11.11.2022
3 12.11.2022
4 13.11.2022
5 14.11.2022
6 15.11.2022
7 16.11.2022
3 17.11.2022
4 18.11.2022
5 19.11.2022
6 20.11.2022
7 21.11.2022
10 22.11.2022
11 23.11.2022
5 24.11.2022
6 25.11.2022
7 26.11.2022
10 27.11.2022
11 28.11.2022
3 29.11.2022
4 30.11.2022
7 01.12.2022
10 02.12.2022
11 03.12.2022
3 04.12.2022
4 05.12.2022
5 06.12.2022
6 07.12.2022
11 08.12.2022
3 09.12.2022
4 10.12.2022
5 11.12.2022
6 12.12.2022
7 13.12.2022
10 14.12.2022
4 15.12.2022
5 16.12.2022
6 17.12.2022
7 18.12.2022
10 19.12.2022
11 20.12.2022
3 21.12.2022
6 22.12.2022
7 23.12.2022
10 24.12.2022
11 25.12.2022
3 26.12.2022
4 27.12.2022
5 28.12.2022
10 29.12.2022
11 30.12.2022
3 31.12.2022
PS。它不像我发布的 plsql 代码那样灵活,它不会对每个 patern_id 超过 2 个空值起作用,有时它会超出 31.12 一点点。模式年的(我标记了规范日期的代码行,如果它超过 31.12。只需减少数字一点)