2017-06-05 71 views
0

我在寫一個PL/SQL過程,該過程給出了基於日期範圍值的查詢計數。我想動態獲取日期範圍,併爲此寫入了一個光標。將值放入不同日期範圍的集合

我正在使用一個集合並獲取每個月的計數,我面對的問題是集合中僅填充了上個月的計數。我想得到所有月份的數量。誰能幫忙?

這是我寫的程序:

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; 

回答

2

bulk collect查詢更換收集的周圍每次循環的內容;它不附加到集合(如果這是你所期望的)。所以在你的循環之後,你只能看到最後一個bulk collect的結果,這是你光標的最後一個月。

你也顯然比較日期爲字符串,這不是一個好主意(除非c2存儲爲一個字符串 - 這是更糟糕的)。由於between是包含性的,如果存儲的時間部分是午夜,您可能會冒險將每月第一天的數據包括在兩個計數中。對日期範圍使用平等檢查更安全。

您不需要使用遊標來獲取該遊標中的日期和單個查詢,只需將當前遊標查詢連接到目標表即可 - 使用外部連接來允許沒有匹配數據的月份。您的光標似乎當年在尋找所有月份,上升到目前的一年的開始,這樣或許可以簡化爲:

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; 

你可以用它來填充您的收藏:

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; 
/

儘管因爲它只存儲/顯示計數,而不會說明它們屬於哪個月,但最終可能並不是您真正需要的。隨着計數的順序,你至少知道集合中的第一個元素代表1月份,我想。

+0

你明白了。謝謝......我現在必須使用utl_file將這些值填充到xls文件中。 –