您可以获得日期范围涵盖的每个月的开始时间;这使用一对虚构的固定值,因为不清楚您从哪里获得范围:
select add_months(trunc(date '2019-03-15', 'MM'), level - 1) as month_start
from dual
connect by level <= ceil(months_between(date '2019-11-21', date '2019-03-15'));
MONTH_STAR
----------
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
9 rows selected.
然后,您可以以各种方式操纵这些日期。您可以使用该next_day()
功能查找该月的第一个星期六 - 基于前一天,以防该月的 1 日本身是星期六。如果再加上 28 天,则得到该月的第五个星期六 - 或者,对于只有四个星期六的月份,下个月的第一个星期六。因此,如果您比较那些生成的星期六,如果它们在同一个月,那么该月实际上必须有五个星期六。
select month_start,
next_day(month_start - 1, 'SATURDAY') as first_sat,
next_day(month_start - 1, 'SATURDAY') + 28 as poss_fifth_sat,
extract(month from month_start) as month_num,
extract(month from (next_day(month_start - 1, 'SATURDAY') + 28)) as poss_fifth_sat_month
from (
select add_months(trunc(date '2019-03-15', 'MM'), level - 1) as month_start
from dual
connect by level <= ceil(months_between(date '2019-11-21', date '2019-03-15'))
);
MONTH_STAR FIRST_SAT POSS_FIFTH MONTH_NUM POSS_FIFTH_SAT_MONTH
---------- ---------- ---------- ---------- --------------------
2019-03-01 2019-03-02 2019-03-30 3 3 -- same
2019-04-01 2019-04-06 2019-05-04 4 5
2019-05-01 2019-05-04 2019-06-01 5 6
2019-06-01 2019-06-01 2019-06-29 6 6 -- same
2019-07-01 2019-07-06 2019-08-03 7 8
2019-08-01 2019-08-03 2019-08-31 8 8 -- same
2019-09-01 2019-09-07 2019-10-05 9 10
2019-10-01 2019-10-05 2019-11-02 10 11
2019-11-01 2019-11-02 2019-11-30 11 11 -- same
9 rows selected.
您实际上不需要查看这些值,我只是在展示工作。但是您可以使用最后两个作为过滤器:
select month_start
from (
select add_months(trunc(date '2019-03-15', 'MM'), level - 1) as month_start
from dual
connect by level <= ceil(months_between(date '2019-11-21', date '2019-03-15'))
)
where extract(month from month_start)
= extract(month from (next_day(month_start - 1, 'SATURDAY') + 28));
MONTH_STAR
----------
2019-03-01
2019-06-01
2019-08-01
2019-11-01
然后,您可以根据需要格式化这些日期。
文档中提到了一个可能的问题(我确定还有其他问题):
参数char必须是会话日期语言中的一周中的一天,可以是全名或缩写。
因此,只要您的会话日期语言是英语,上面的代码就可以工作。如果您可以 100% 确定运行它的每个人将始终使用相同的会话设置,那么您使用该固定值(或任何合适的语言)。
如果您无法控制它,那么您就无法像使用其他一些功能那样覆盖日期语言。作为一种解决方法,您可以使用已知的星期六日期来获取当前日期语言的名称或星期六的缩写,而无需知道该语言实际上是什么:
alter session set nls_date_language = 'Spanish';
select month_start
from (
select add_months(trunc(date '2019-03-15', 'MM'), level - 1) as month_start
from dual
connect by level <= ceil(months_between(date '2019-11-21', date '2019-03-15'))
)
where extract(month from month_start)
= extract(month from (next_day(month_start - 1, to_char(date '2000-01-01', 'Dy')) + 28));
MONTH_STAR
----------
2019-03-01
2019-06-01
2019-08-01
2019-11-01