从给定模式 Oracle 构造模式

Construct pattern from a given pattern Oracle

我想根据存储在 view.Generate 未来 1 年模式中的给定模式构建系列。我尝试使用 row_numberconnect byLead ,但无法构建。 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。只需减少数字一点)