0

如何在oracle中获取2013年每个月的最后一个星期四?我需要将此日期更新到我的表格中。

我需要像这样的输出

Last Thursday in a year 2013 
----------------------
31.01.2013
28.02.2013
28.03.2013
24.04.2013
30.05.2013
27.06.2013
25.07.2013
29.08.2013
26.09.2013
31.10.2013
28.11.2013
26.12.2013

感谢做需要的。

4

4 回答 4

12

这将做到:

select next_day (last_day (add_months(date '2013-01-01', rownum-1))-7, 'THU') as thurs
from dual
connect by level <= 12;

THURS
---------
31-JAN-13
28-FEB-13
28-MAR-13
25-APR-13
30-MAY-13
27-JUN-13
25-JUL-13
29-AUG-13
26-SEP-13
31-OCT-13
28-NOV-13
26-DEC-13

12 rows selected.

解释:

1)下面select是生成一系列整数1..12的方法:

select rownum from dual connect by level <= 12;

2) 这将返回 2012 年 12 个月中的第 1 个月,取 2013 年 1 月 1 日并添加 0 个月、1 个月、...、11 个月:

select add_months(date '2013-01-01', rownum-1)
from dual connect by level <= 12;

3) 该last_day函数返回给定日期该月的最后一天,因此我们现在有 2013-01-31、2013-02-28、...、2013-12-31。

4)next_day (date, 'THU')返回指定日期后的下一个星期四。为了得到这个月的最后一个星期四,我们取这个月的最后一天,返回 7 天,然后找到下一个星期四。

于 2013-06-20T12:55:03.427 回答
4

我会去dbms_scheduler

declare
  start_dt              date := date '2013-01-01';
  months_last_thursday  date;

begin

  loop

    dbms_scheduler.evaluate_calendar_string (

       calendar_string   => 'FREQ=MONTHLY;BYDAY=-1 THU',
       start_date        =>  start_dt,
       return_date_after =>  start_dt, 
       next_run_date     =>  months_last_thursday

    );

    exit when months_last_thursday > date '2013-12-31';

    dbms_output.put_line(months_last_thursday);

    start_dt := months_last_thursday;

  end loop;
end;
/
于 2013-06-20T13:02:26.600 回答
0

基于@Rene 的回答,这可以扩展到一般(通用?)解决方案:

CREATE OR REPLACE FUNCTION recurring_dates (p_year IN NUMBER, p_rule IN VARCHAR) 
  RETURN dbms_stats.datearray PIPELINED
AS
  start_dt DATE;
  last_dt  DATE;
  next_dt  DATE;
BEGIN
  start_dt := to_date(to_char(p_year,'fm0000')||'01-01','YYYY-MM-DD');
  last_dt  := to_date(to_char(p_year,'fm0000')||'12-31','YYYY-MM-DD');
  LOOP
    dbms_scheduler.evaluate_calendar_string(
      calendar_string   => p_rule, 
      start_date        => start_dt,
      return_date_after => start_dt,
      next_run_date     => next_dt);
    EXIT WHEN next_dt > last_dt;
    PIPE ROW (next_dt);
    start_dt := next_dt;
  END LOOP;
END recurring_dates;
/

您可以在DBMS_SCHEDULER-Syntax 中为该函数提供一个日历字符串,它将返回匹配的日期。

@rcmuthu786 的最后一个星期四:

SELECT * FROM TABLE(recurring_dates (2013, 'FREQ=MONTHLY;BYDAY=-1 THU'));

2013-01-31
2013-02-28
2013-03-28
2013-04-25
2013-05-30
...

或者,每个月的第二个星期三:

SELECT * FROM TABLE(recurring_dates (2013, 'FREQ=MONTHLY;BYDAY=2 WED'));
2013-01-09
2013-02-13
2013-03-13
2013-04-10
...

等等等等……

于 2013-06-20T14:40:47.993 回答
-1

最优雅的方式如下

select thdate from (
select a.*, row_number() over (partition by to_char(thdate,'yyyymm'),day order by thdate desc) row_rank
 from (
select trunc(sysdate,'YEAR') + rownum-1 thdate,
trim(to_char(trunc(sysdate,'YEAR') + rownum-1,'DAY')) day from dba_objects 
where trunc(sysdate,'YEAR') + rownum-1 <
trunc(sysdate+365,'YEAR')
) a where day='THURSDAY'
) where row_rank=1

于 2013-06-20T16:12:43.110 回答