2017-06-05 1 views
0

Ich schreibe eine PL/SQL-Prozedur, die die Anzahl einer Abfrage basierend auf Datenbereichswerten angibt. Ich möchte den Datumsbereich dynamisch abrufen und habe dafür einen Cursor geschrieben.Werte in eine Sammlung für verschiedene Zeiträume einfügen

Ich benutze eine Sammlung und bekomme die Zählungen jedes Monats, das Problem, mit dem ich konfrontiert bin, ist, dass die Sammlung mit der Zählung des letzten Monats allein gefüllt ist. Ich möchte die Zählung aller Monate bekommen. Kann jemand helfen?

Dies ist das Verfahren, die ich geschrieben habe:

create or replace 
Procedure Sample As 
    Cursor C1 Is 
     With T As (
      select to_date('01-JAN-17') start_date, 
       Last_Day(Add_Months(Sysdate,-1)) end_date from dual 
     ) 
     Select To_Char(Add_Months(Trunc(Start_Date,'mm'),Level - 1),'DD-MON-YY') St_Date, 
      to_char(add_months(trunc(start_date,'mm'),level),'DD-MON-YY') ed_date 
     From T 
     Connect By Trunc(End_Date,'mm') >= Add_Months(Trunc(Start_Date,'mm'),Level - 1); 

    Type T_count_Group_Id Is Table Of number; 
    V_count_Group_Id T_count_Group_Id; 
Begin 
    For I In C1 
    Loop 
     Select Count(Distinct c1) bulk collect Into V_Count_Group_Id From T1 
     Where C2 Between I.St_Date And I.Ed_Date; 
    End Loop; 
    For J In V_Count_Group_Id.First..V_Count_Group_Id.Last 
    Loop 
     Dbms_Output.Put_Line(V_Count_Group_Id(J)); 
    end loop; 
END SAMPLE; 

Antwort

2

Ihre bulk collect Abfrage wird den Inhalt der Sammlung jedes Mal um die Schleife zu ersetzen; es hängt nicht an die Sammlung an (wenn das das ist, was Sie erwartet haben). Nach Ihrer Schleife sehen Sie nur das Ergebnis der letzten bulk collect, die der letzte Monat von Ihrem Cursor ist.

Sie vergleichen auch Daten als String, was keine gute Idee ist (es sei denn, c2 wird als String gespeichert - was noch schlimmer ist). Und da between inklusive ist, riskieren Sie, Daten für den ersten Tag jedes Monats in zwei Zählungen einzubeziehen, wenn der gespeicherte Zeitabschnitt Mitternacht ist. Es ist sicherer, Gleichheitsprüfungen für Datumsbereiche zu verwenden.

Sie müssen nicht einen Cursor verwenden, um die Daten und dann einzelne Abfragen innerhalb des Cursors zu erhalten. Sie können Ihre aktuelle Cursor-Abfrage einfach an die Zieltabelle anfügen - mit einem äußeren Join für Monate ohne übereinstimmende Daten . Der Cursor erscheint für alle Monate im laufenden Jahr zu suchen, bis zum Beginn des laufenden Jahres, so dass vielleicht vereinfacht werden könnte:

with t as (
    select add_months(trunc(sysdate, 'YYYY'), level - 1) as st_date, 
    add_months(trunc(sysdate, 'YYYY'), level) as ed_date 
    from dual 
    connect by level < extract(month from sysdate) 
) 
select t.st_date, t.ed_date, count(distinct t1.c1) 
from t 
left join t1 on t1.c2 >= t.st_date and t1.c2 < t.ed_date 
group by t.st_date, t.ed_date 
order by t.st_date; 

Sie, dass Ihre Sammlung füllen verwenden können:

declare 
    type t_count_group_id is table of number; 
    v_count_group_id t_count_group_id; 
begin 
    with t as (
    select add_months(trunc(sysdate, 'YYYY'), level - 1) as st_date, 
     add_months(trunc(sysdate, 'YYYY'), level) as ed_date 
    from dual 
    connect by level < extract(month from sysdate) 
) 
    select count(distinct t1.c1) 
    bulk collect into v_count_group_id 
    from t 
    left join t1 on t1.c2 >= t.st_date and t1.c2 < t.ed_date 
    group by t.st_date, t.ed_date 
    order by t.st_date; 

    for j in v_count_group_id.first..v_count_group_id.last 
    loop 
    dbms_output.put_line(v_count_group_id(j)); 
    end loop; 
end; 
/

Obwohl es nur die Counts speichert/anzeigt, ohne zu sagen, zu welchem ​​Monat sie gehören, könnte das letztendlich nicht das sein, was Sie wirklich brauchen. Da die Zählungen geordnet sind, wissen Sie zumindest, dass das erste Element in der Sammlung Januar darstellt, nehme ich an.

+0

Sie haben es richtig gemacht. Danke ... Ich muss nun diese Werte mit utl_file in eine xls-Datei auffüllen. –

Verwandte Themen