-- Oracle (21)
with
current_date as (
select trunc(sysdate) as cd from dual
),
t as (
select
cd as today,
trunc(cd, 'MM') as first_day_of_month,
add_months(trunc(cd, 'MM'), 1) - 1 as last_day_of_month,
to_char(trunc(cd, 'MM'), 'IW') as week_of_fdm,
to_char(add_months(trunc(cd, 'MM'), 1) - 1, 'IW') as week_of_ldm
from current_date
),
days_set as (
select
level as lvl,
t.first_day_of_month -7 + level-1 as day,
to_char(t.first_day_of_month -7 + level-1, 'IW') as week_id
from t
connect by (t.first_day_of_month -7 + level-1) < (t.last_day_of_month +7)
),
days_and_week as (
select
days_set.lvl,
case
when days_set.day between t.first_day_of_month and t.last_day_of_month
then lpad(ltrim(to_char(days_set.day, 'DD'), '0'), 2, ' ')
when days_set.day < t.first_day_of_month
then ' '
when days_set.day > t.last_day_of_month
then ' '
else ''
end as dd,
week_id
from days_set, t
where days_set.week_id between t.week_of_fdm and week_of_ldm
)
select
'пн | вт | ср | чт | пт | сб | вс' as calendar
from dual
union all
select
listagg(dd, ' | ') within group(order by lvl)
from days_and_week
group by week_id
;