简体   繁体   中英

Oracle - How to repeat query for every year/month/week

I've made a query to get the rows from my chosen columns where the date is 2018 December:

SELECT myColumn1, myColumn2 
FROM MyTable
WHERE to_char(myColumn_DATE, 'YYYY/MM') = '2018/12'

This is quite simple and I can now use these rows to create some further logic. However what if I need to repeat this for every month in a given year, or even every week?

I'm exporting the query results into separate excel tables, so I guess I would have to manually check the correct date intervals every time and can't aggregate the data for a whole year/month/etc. Isn't there some PL/SQL approach to avoid this tedious repetition?

Assume you're on a day from December 2018, and your aim is to populate the table MyTable2 through the data from the table MyTable .

Firstly, let's create MyTable2 without data :

create table MyTable2 as
select myColumn1, myColumn2 
  from MyTable
 where 1 = 9;

and then create a procedure by which populate MyTable2 on the last day of every month

create or replace procedure pr_populate_Mytable2 is
begin
   insert into MyTable2
   select myColumn1, myColumn2 
     from MyTable
    where to_char(myColumn_DATE, 'YYYY/MM') = to_char(sysdate,'YYYY/MM');
 commit;
end;

by calling the procedure from a dbms_scheduler as

declare
    v_job_name varchar2(32) := 'jb_populate_Mytable2';
begin  
    dbms_scheduler.create_job(
        job_name => v_job_name,
        job_type => 'STORED_PROCEDURE',
        job_action => 'pr_populate_Mytable2', 
        start_date => to_date('31-12-2018 20:00:00', 'dd-mm-yyyy hh24:mi:ss'),
        repeat_interval => 'FREQ=MONTHLY; BYMONTHDAY=-1; BYHOUR=21;',
        auto_drop => false,
        comments => 'Populates our table on the last day of every month at 21 o''clock ');

    dbms_scheduler.enable(v_job_name);    
end;

starts at 8pm on the last day of december, and repeats on every upcoming last days of the months at 9pm in the future.

You can use the CONNECT BY LEVEL <= trick to generate rows, and then use a combination of date functions to generate the relevant dates.

--Months for the current year.
select add_months(trunc(sysdate, 'year'), level-1) the_month
from dual
connect by level <= 12;

THE_MONTH
---------
2019-01-01
2019-02-01
2019-03-01
2019-04-01
2019-05-01
2019-06-01
2019-07-01
2019-08-01
2019-09-01
2019-10-01
2019-11-01
2019-12-01

Then create an inline view with that query, and join it to the main table:

select *
from
(
    --Months for the current year.
    select add_months(trunc(sysdate, 'year'), level-1) the_month
    from dual
    connect by level <= 12
) months
left join mytable
    on months.the_month = trunc(mycolumn_date, 'month');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM