Generate rows
select level as N
from dual
connect by level <= 10
N | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|
Generate days
select date'2021-01-01'
+ level - 1 as dt
from dual
connect by level <= 31
DT | 01-JAN-21 | 02-JAN-21 | 03-JAN-21 | 04-JAN-21 | 05-JAN-21 | 06-JAN-21 | 07-JAN-21 | 08-JAN-21 | 09-JAN-21 | 10-JAN-21 | 11-JAN-21 | 12-JAN-21 | 13-JAN-21 | 14-JAN-21 | 15-JAN-21 | 16-JAN-21 | 17-JAN-21 | 18-JAN-21 | 19-JAN-21 | 20-JAN-21 | 21-JAN-21 | 22-JAN-21 | 23-JAN-21 | 24-JAN-21 | 25-JAN-21 | 26-JAN-21 | 27-JAN-21 | 28-JAN-21 | 29-JAN-21 | 30-JAN-21 | 31-JAN-21 |
---|
Show orders per day
with rws as (
select min ( order_datetime ) mn_dt,
max ( order_datetime ) mx_dt
from co.orders o
), dates as (
select trunc ( mn_dt ) + level - 1 dt
from rws
connect by level <= (
extract ( day from ( mx_dt - mn_dt ) ) + 1
)
)
select dt, count(order_datetime) from dates
left join co.orders
on dt <= order_datetime
and dt + 1 > order_datetime
group by dt
order by dt
DT | COUNT(ORDER_DATETIME) | 04-FEB-18 | 1 | 05-FEB-18 | 0 | 06-FEB-18 | 0 | 07-FEB-18 | 0 | 08-FEB-18 | 1 | 09-FEB-18 | 1 | 10-FEB-18 | 1 | 11-FEB-18 | 1 | 12-FEB-18 | 0 | 13-FEB-18 | 1 | 14-FEB-18 | 0 | 15-FEB-18 | 0 | 16-FEB-18 | 0 | 17-FEB-18 | 0 | 18-FEB-18 | 0 | 19-FEB-18 | 0 | 20-FEB-18 | 0 | 21-FEB-18 | 0 | 22-FEB-18 | 2 | 23-FEB-18 | 2 | 24-FEB-18 | 4 | 25-FEB-18 | 0 | 26-FEB-18 | 2 | 27-FEB-18 | 1 | 28-FEB-18 | 1 | 01-MAR-18 | 4 | 02-MAR-18 | 2 | 03-MAR-18 | 3 | 04-MAR-18 | 0 | 05-MAR-18 | 1 | 06-MAR-18 | 2 | 07-MAR-18 | 2 | 08-MAR-18 | 1 | 09-MAR-18 | 2 | 10-MAR-18 | 2 | 11-MAR-18 | 1 | 12-MAR-18 | 5 | 13-MAR-18 | 2 | 14-MAR-18 | 4 | 15-MAR-18 | 3 | 16-MAR-18 | 2 | 17-MAR-18 | 2 | 18-MAR-18 | 2 | 19-MAR-18 | 1 | 20-MAR-18 | 1 | 21-MAR-18 | 1 | 22-MAR-18 | 5 | 23-MAR-18 | 2 | 24-MAR-18 | 2 | 25-MAR-18 | 1 |
---|
Show orders per day for a store
with stor as (
select store_id, order_datetime
from co.orders o
where store_id = 23
), rws as (
select min ( trunc ( order_datetime ) ) mn_dt,
max ( trunc ( order_datetime ) ) mx_dt
from stor
)
select dt, count ( order_datetime ) from (
select mn_dt + level - 1 as dt
from rws
connect by level <= mx_dt - mn_dt + 1
)
left join stor
on dt <= order_datetime
and dt + 1 > order_datetime
group by dt
order by dt
DT | COUNT(ORDER_DATETIME) | 22-MAR-19 | 1 | 23-MAR-19 | 0 | 24-MAR-19 | 2 | 25-MAR-19 | 2 | 26-MAR-19 | 1 | 27-MAR-19 | 2 | 28-MAR-19 | 1 | 29-MAR-19 | 0 | 30-MAR-19 | 0 | 31-MAR-19 | 2 | 01-APR-19 | 3 | 02-APR-19 | 1 | 03-APR-19 | 2 | 04-APR-19 | 0 | 05-APR-19 | 1 | 06-APR-19 | 0 | 07-APR-19 | 0 | 08-APR-19 | 3 | 09-APR-19 | 0 | 10-APR-19 | 3 | 11-APR-19 | 3 | 12-APR-19 | 1 |
---|
Find the Fridays in 2021
with rws as (
select date'2021-01-01'
+ level - 1 as dt
from dual
connect by level <= (
date'2022-01-01' - date'2021-01-01'
)
)
select * from rws
where to_char ( dt, 'FMDay' ) = 'Friday'
DT | 01-JAN-21 | 08-JAN-21 | 15-JAN-21 | 22-JAN-21 | 29-JAN-21 | 05-FEB-21 | 12-FEB-21 | 19-FEB-21 | 26-FEB-21 | 05-MAR-21 | 12-MAR-21 | 19-MAR-21 | 26-MAR-21 | 02-APR-21 | 09-APR-21 | 16-APR-21 | 23-APR-21 | 30-APR-21 | 07-MAY-21 | 14-MAY-21 | 21-MAY-21 | 28-MAY-21 | 04-JUN-21 | 11-JUN-21 | 18-JUN-21 | 25-JUN-21 | 02-JUL-21 | 09-JUL-21 | 16-JUL-21 | 23-JUL-21 | 30-JUL-21 | 06-AUG-21 | 13-AUG-21 | 20-AUG-21 | 27-AUG-21 | 03-SEP-21 | 10-SEP-21 | 17-SEP-21 | 24-SEP-21 | 01-OCT-21 | 08-OCT-21 | 15-OCT-21 | 22-OCT-21 | 29-OCT-21 | 05-NOV-21 | 12-NOV-21 | 19-NOV-21 | 26-NOV-21 | 03-DEC-21 | 10-DEC-21 |
---|
Find all the Fridays - improved
with rws as (
select next_day ( date'2021-01-01' - 1, 'Friday' )
+ ( level - 1 ) * 7 as dt
from dual
connect by level <= (
( date'2021-12-31' - next_day ( date'2021-01-01' - 1, 'Friday' ) + 7 ) / 7
)
)
select dt from rws
DT | 01-JAN-21 | 08-JAN-21 | 15-JAN-21 | 22-JAN-21 | 29-JAN-21 | 05-FEB-21 | 12-FEB-21 | 19-FEB-21 | 26-FEB-21 | 05-MAR-21 | 12-MAR-21 | 19-MAR-21 | 26-MAR-21 | 02-APR-21 | 09-APR-21 | 16-APR-21 | 23-APR-21 | 30-APR-21 | 07-MAY-21 | 14-MAY-21 | 21-MAY-21 | 28-MAY-21 | 04-JUN-21 | 11-JUN-21 | 18-JUN-21 | 25-JUN-21 | 02-JUL-21 | 09-JUL-21 | 16-JUL-21 | 23-JUL-21 | 30-JUL-21 | 06-AUG-21 | 13-AUG-21 | 20-AUG-21 | 27-AUG-21 | 03-SEP-21 | 10-SEP-21 | 17-SEP-21 | 24-SEP-21 | 01-OCT-21 | 08-OCT-21 | 15-OCT-21 | 22-OCT-21 | 29-OCT-21 | 05-NOV-21 | 12-NOV-21 | 19-NOV-21 | 26-NOV-21 | 03-DEC-21 | 10-DEC-21 |
---|
Set session language to Spanish
alter session set nls_language = Spanish
Statement processed.
Language settings for next_day
select next_day ( date'2021-01-01', 'Friday' ) from dual
ORA-01846: día de la semana no válidoMore Details: https://docs.oracle.com/error-help/db/ora-01846
Set session language back to English
alter session set nls_language = English
Statement processed.
Language settings for next_day
select next_day ( date'2021-01-01', 'Viernes' ) from dual
ORA-01846: not a valid day of the weekMore Details: https://docs.oracle.com/error-help/db/ora-01846
Generate months
select add_months (
date'2021-01-01',
level - 1
) as dt
from dual
connect by level <= months_between (
date'2021-12-31',
date'2021-01-01'
) + 1
DT | 01-JAN-21 | 01-FEB-21 | 01-MAR-21 | 01-APR-21 | 01-MAY-21 | 01-JUN-21 | 01-JUL-21 | 01-AUG-21 | 01-SEP-21 | 01-OCT-21 | 01-NOV-21 | 01-DEC-21 |
---|
select add_months (
date'2021-01-15',
level - 1
) as dt
from dual
connect by level <= months_between (
date'2022-01-15',
date'2021-01-15'
) + 1
DT | 15-JAN-21 | 15-FEB-21 | 15-MAR-21 | 15-APR-21 | 15-MAY-21 | 15-JUN-21 | 15-JUL-21 | 15-AUG-21 | 15-SEP-21 | 15-OCT-21 | 15-NOV-21 | 15-DEC-21 | 15-JAN-22 |
---|
Generate month start and end dates
with mths as (
select add_months (
date'2021-01-15',
level - 1
) as dt
from dual
connect by level <= months_between (
date'2022-01-15',
date'2021-01-15'
) + 1
)
select case rownum
when 1 then dt
else trunc ( dt, 'mm' )
end start_date,
lead (
trunc ( dt, 'mm' ) - 1,
1, dt
) over (
order by dt
) end_date
from mths
START_DATE | END_DATE | 15-JAN-21 | 31-JAN-21 | 01-FEB-21 | 28-FEB-21 | 01-MAR-21 | 31-MAR-21 | 01-APR-21 | 30-APR-21 | 01-MAY-21 | 31-MAY-21 | 01-JUN-21 | 30-JUN-21 | 01-JUL-21 | 31-JUL-21 | 01-AUG-21 | 31-AUG-21 | 01-SEP-21 | 30-SEP-21 | 01-OCT-21 | 31-OCT-21 | 01-NOV-21 | 30-NOV-21 | 01-DEC-21 | 31-DEC-21 | 01-JAN-22 | 15-JAN-22 |
---|
Generate years
select date'2021-01-01'
+ numtoyminterval ( level - 1, 'year' ) as dt
from dual
connect by level <= ( months_between (
date'2022-12-31',
date'2020-01-01'
) / 12 ) + 1
DT | 01-JAN-21 | 01-JAN-22 | 01-JAN-23 |
---|
Make these reusable with SQL macros
create or replace package date_mgr as
function generate_days (
start_date date, end_date date,
day_increment integer default 1
)
return varchar2 sql_macro;
function generate_months (
start_date date, end_date date,
month_increment integer default 1
)
return varchar2 sql_macro;
function generate_years (
start_date date, end_date date,
year_increment integer default 1
)
return varchar2 sql_macro;
end date_mgr;
Package created.
Make these reusable with SQL macros
create or replace package body date_mgr as
function generate_days (
start_date date, end_date date,
day_increment integer default 1
)
return varchar2 sql_macro as
stmt varchar2(4000);
begin
stmt := 'select start_date
+ ( level - 1 ) * day_increment as dt
from dual
connect by level <= (
( ( end_date - start_date ) + day_increment ) / day_increment
)';
dbms_output.put_line ( stmt );
return stmt;
end generate_days;
function generate_months (
start_date date, end_date date,
month_increment integer default 1
)
return varchar2 sql_macro as
stmt varchar2(4000);
begin
stmt := '
select add_months (
start_date,
( level - 1 ) * month_increment
) as dt
from dual
connect by level <= ( months_between (
end_date,
start_date
) + month_increment ) / month_increment';
dbms_output.put_line ( stmt );
return stmt;
end generate_months;
function generate_years (
start_date date, end_date date,
year_increment integer default 1
)
return varchar2 sql_macro as
stmt varchar2(4000);
begin
stmt := q'!
select start_date
+ numtoyminterval ( ( level - 1 ) * year_increment, 'year' ) as dt
from dual
connect by level <= ( ( months_between (
end_date,
start_date
) / 12 ) + year_increment ) / year_increment!';
dbms_output.put_line ( stmt );
return stmt;
end generate_years;
end date_mgr;
Package Body created.
Generate days using SQL macro
select * from date_mgr.generate_days (
date'2021-01-01',
date'2021-01-31'
)
DT | 01-JAN-21 | 02-JAN-21 | 03-JAN-21 | 04-JAN-21 | 05-JAN-21 | 06-JAN-21 | 07-JAN-21 | 08-JAN-21 | 09-JAN-21 | 10-JAN-21 | 11-JAN-21 | 12-JAN-21 | 13-JAN-21 | 14-JAN-21 | 15-JAN-21 | 16-JAN-21 | 17-JAN-21 | 18-JAN-21 | 19-JAN-21 | 20-JAN-21 | 21-JAN-21 | 22-JAN-21 | 23-JAN-21 | 24-JAN-21 | 25-JAN-21 | 26-JAN-21 | 27-JAN-21 | 28-JAN-21 | 29-JAN-21 | 30-JAN-21 | 31-JAN-21 |
---|
Generate every Friday using SQL macro
select * from date_mgr.generate_days (
next_day ( date'2021-01-01' - 1, 'Friday' ),
date'2021-12-31',
7
)
DT | 01-JAN-21 | 08-JAN-21 | 15-JAN-21 | 22-JAN-21 | 29-JAN-21 | 05-FEB-21 | 12-FEB-21 | 19-FEB-21 | 26-FEB-21 | 05-MAR-21 | 12-MAR-21 | 19-MAR-21 | 26-MAR-21 | 02-APR-21 | 09-APR-21 | 16-APR-21 | 23-APR-21 | 30-APR-21 | 07-MAY-21 | 14-MAY-21 | 21-MAY-21 | 28-MAY-21 | 04-JUN-21 | 11-JUN-21 | 18-JUN-21 | 25-JUN-21 | 02-JUL-21 | 09-JUL-21 | 16-JUL-21 | 23-JUL-21 | 30-JUL-21 | 06-AUG-21 | 13-AUG-21 | 20-AUG-21 | 27-AUG-21 | 03-SEP-21 | 10-SEP-21 | 17-SEP-21 | 24-SEP-21 | 01-OCT-21 | 08-OCT-21 | 15-OCT-21 | 22-OCT-21 | 29-OCT-21 | 05-NOV-21 | 12-NOV-21 | 19-NOV-21 | 26-NOV-21 | 03-DEC-21 | 10-DEC-21 |
---|
Generate every other Monday
select * from date_mgr.generate_days (
next_day ( date'2021-01-01' - 1, 'Monday' ),
date'2021-12-31',
14
)
DT | 04-JAN-21 | 18-JAN-21 | 01-FEB-21 | 15-FEB-21 | 01-MAR-21 | 15-MAR-21 | 29-MAR-21 | 12-APR-21 | 26-APR-21 | 10-MAY-21 | 24-MAY-21 | 07-JUN-21 | 21-JUN-21 | 05-JUL-21 | 19-JUL-21 | 02-AUG-21 | 16-AUG-21 | 30-AUG-21 | 13-SEP-21 | 27-SEP-21 | 11-OCT-21 | 25-OCT-21 | 08-NOV-21 | 22-NOV-21 | 06-DEC-21 | 20-DEC-21 |
---|
Generate months using SQL macro
select * from date_mgr.generate_months (
next_day ( date'2021-01-01' - 1, 'Monday' ),
date'2021-12-31'
)
DT | 04-JAN-21 | 04-FEB-21 | 04-MAR-21 | 04-APR-21 | 04-MAY-21 | 04-JUN-21 | 04-JUL-21 | 04-AUG-21 | 04-SEP-21 | 04-OCT-21 | 04-NOV-21 | 04-DEC-21 |
---|
Generate quarters
select * from date_mgr.generate_months (
date'2021-01-01',
date'2021-12-31',
3
)
DT | 01-JAN-21 | 01-APR-21 | 01-JUL-21 | 01-OCT-21 |
---|
Generate three years with SQL macros
select * from date_mgr.generate_years (
date'2020-01-01',
date'2022-12-31'
)
DT | 01-JAN-20 | 01-JAN-21 | 01-JAN-22 |
---|
with stor as (
select store_id, order_datetime
from co.orders o
where store_id = 23
), rws as (
select min ( trunc ( order_datetime ) ) mn_dt,
max ( trunc ( order_datetime ) ) mx_dt
from stor
)
select dt, count ( order_datetime ) from (
select *
from rws
cross join date_mgr.generate_days ( mn_dt, mx_dt )
)
left join stor
on dt <= order_datetime
and dt + 1 > order_datetime
group by dt
order by dt
DT | COUNT(ORDER_DATETIME) | 22-MAR-19 | 1 | 23-MAR-19 | 0 | 24-MAR-19 | 2 | 25-MAR-19 | 2 | 26-MAR-19 | 1 | 27-MAR-19 | 2 | 28-MAR-19 | 1 | 29-MAR-19 | 0 | 30-MAR-19 | 0 | 31-MAR-19 | 2 | 01-APR-19 | 3 | 02-APR-19 | 1 | 03-APR-19 | 2 | 04-APR-19 | 0 | 05-APR-19 | 1 | 06-APR-19 | 0 | 07-APR-19 | 0 | 08-APR-19 | 3 | 09-APR-19 | 0 | 10-APR-19 | 3 | 11-APR-19 | 3 | 12-APR-19 | 1 |
---|
Create a dates table
create table calendar_dates (
calendar_date date
check ( calendar_date = trunc ( calendar_date ) )
not null
primary key,
is_working_day integer
check ( is_working_day in ( 0, 1 ) )
not null,
day_of_week varchar2(10 char)
) organization index
Table created.
Store days of the year
insert into calendar_dates (
calendar_date, is_working_day, day_of_week
)
select dt,
case
when to_char ( dt, 'dy', 'nls_date_language = english' )
in ( 'sat', 'sun' ) then 0
else 1
end,
to_char ( dt, 'FMDay', 'nls_date_language = english' )
from date_mgr.generate_days (
date'2021-01-01', date'2021-12-31', 1
)
365 row(s) inserted.
select start_date + ( level - 1 ) * day_increment as dt from dual connect by level <= ( ( ( end_date - start_date ) + day_increment ) / day_increment )
select start_date + ( level - 1 ) * day_increment as dt from dual connect by level <= ( ( ( end_date - start_date ) + day_increment ) / day_increment )
Set UK public holidays to be non-working days
update calendar_dates
set is_working_day = 0
where calendar_date in (
date'2021-01-01',
date'2021-04-02',
date'2021-04-05',
date'2021-05-03',
date'2021-05-31',
date'2021-08-30',
date'2021-12-27',
date'2021-12-28'
)
8 row(s) updated.
commit
Statement processed.
Find all the Mondays in the year
select calendar_date from calendar_dates
where day_of_week = 'Monday'
and calendar_date between date'2021-01-01' and date'2021-12-31'
CALENDAR_DATE | 04-JAN-21 | 11-JAN-21 | 18-JAN-21 | 25-JAN-21 | 01-FEB-21 | 08-FEB-21 | 15-FEB-21 | 22-FEB-21 | 01-MAR-21 | 08-MAR-21 | 15-MAR-21 | 22-MAR-21 | 29-MAR-21 | 05-APR-21 | 12-APR-21 | 19-APR-21 | 26-APR-21 | 03-MAY-21 | 10-MAY-21 | 17-MAY-21 | 24-MAY-21 | 31-MAY-21 | 07-JUN-21 | 14-JUN-21 | 21-JUN-21 | 28-JUN-21 | 05-JUL-21 | 12-JUL-21 | 19-JUL-21 | 26-JUL-21 | 02-AUG-21 | 09-AUG-21 | 16-AUG-21 | 23-AUG-21 | 30-AUG-21 | 06-SEP-21 | 13-SEP-21 | 20-SEP-21 | 27-SEP-21 | 04-OCT-21 | 11-OCT-21 | 18-OCT-21 | 25-OCT-21 | 01-NOV-21 | 08-NOV-21 | 15-NOV-21 | 22-NOV-21 | 29-NOV-21 | 06-DEC-21 | 13-DEC-21 |
---|
Find working Mondays in year
select calendar_date from calendar_dates
where day_of_week = 'Monday'
and calendar_date between date'2021-01-01' and date'2021-12-31'
and is_working_day = 1
CALENDAR_DATE | 04-JAN-21 | 11-JAN-21 | 18-JAN-21 | 25-JAN-21 | 01-FEB-21 | 08-FEB-21 | 15-FEB-21 | 22-FEB-21 | 01-MAR-21 | 08-MAR-21 | 15-MAR-21 | 22-MAR-21 | 29-MAR-21 | 12-APR-21 | 19-APR-21 | 26-APR-21 | 10-MAY-21 | 17-MAY-21 | 24-MAY-21 | 07-JUN-21 | 14-JUN-21 | 21-JUN-21 | 28-JUN-21 | 05-JUL-21 | 12-JUL-21 | 19-JUL-21 | 26-JUL-21 | 02-AUG-21 | 09-AUG-21 | 16-AUG-21 | 23-AUG-21 | 06-SEP-21 | 13-SEP-21 | 20-SEP-21 | 27-SEP-21 | 04-OCT-21 | 11-OCT-21 | 18-OCT-21 | 25-OCT-21 | 01-NOV-21 | 08-NOV-21 | 15-NOV-21 | 22-NOV-21 | 29-NOV-21 | 06-DEC-21 | 13-DEC-21 | 20-DEC-21 |
---|