2

過去1年間の各月について、その月の第3金曜日のテーブルを作成しようとしています。一度に1か月間これを行う方法を知っていますが、代わりに日付の範囲を返すのに問題があります。私はforループを使用してこれを実行しようとしました:

create table fridays as
begin
 for i in 1..365
   loop
     select next_day(trunc(sysdate - i,'MM')+13,'FRIDAY') third_friday 
  from dual
end loop;

これらの値を入れるために配列が必要ですか、それとも他の場所で問題が発生していますか?

4

4 に答える 4

3

このようなことを意味しますか?

select dt
  from (select dt,
               row_number() over(partition by to_char(dt, 'mm') order by dt) wn
          from (select trunc(sysdate, 'mm') - level dt
                  from dual
                connect by level < 365)
         where to_char(dt, 'd') = 6)
 where wn = 3

ここにsqlfiddleのデモがあります


更新@APCのコメントを参照して:

NLS_TERRITORY に依存したくない場合は、次のようにすることができます。

select dt
  from (select dt,
               row_number() over(partition by to_char(dt, 'mm') order by dt) wn
          from (select trunc(sysdate, 'mm') - level dt
                  from dual
                connect by level < 365)
         where to_char(dt, 'dy', 'nls_date_language=AMERICAN') = 'fri')
 where wn = 3
于 2013-01-30T11:40:31.357 に答える
1

これは少し不格好ですが、ほとんど直感的な方法です。

select next_day(
         next_day(
           next_day(
             add_months(date '2000-01-01',rownum-1)-1,
             'THURSDAY'),
           'THURSDAY'),
       'THURSDAY')
from    dual
connect by level <= 12
于 2013-01-30T12:18:24.817 に答える
0

もう1つあります:

Select Months, Last_Fri, Total_Fridays
    , (CASE WHEN Total_Fridays = 4 THEN Last_Fri-7 ELSE Last_Fri-14 END) third_fri
 From
 (
  Select To_Char(dt,'Month') Months
       , Next_Day(Last_Day(dt),'FRI')-7 Last_Fri
      , Ceil(to_number(to_char(next_day(last_day(dt)-7,'FRI'),'DD'))/7) Total_Fridays
   From 
 (
  Select add_months(trunc(sysdate,'YEAR'),level-1) dt
   From dual
 Connect By Level <= 12
 ))
/

SQL>
MONTHS  LAST_FRI    TOTAL_FRIDAYS   THIRD_FRI
--------------------------------------------------
January     1/25/2013   4   1/18/2013
February    2/22/2013   4   2/15/2013
March       3/29/2013   5   3/15/2013
April       4/26/2013   4   4/19/2013
May         5/31/2013   5   5/17/2013
June        6/28/2013   4   6/21/2013
July        7/26/2013   4   7/19/2013
August      8/30/2013   5   8/16/2013
September   9/27/2013   4   9/20/2013
October     10/25/2013  4   10/18/2013
November    11/29/2013  5   11/15/2013
December    12/27/2013  4   12/20/2013
于 2013-01-30T16:17:53.557 に答える
0

これらのトリッキーな相対日付の問題に対する便利な手法の 1 つは、DBMS_Schedular カレンダー構文を使用することです

DBMS_Scheduler には、複雑なカレンダー仕様に適した非常に包括的なカレンダー構文があり (慣れれば)、Evaluate_Calendar_String 関数は、指定された日付の後にスケジュール仕様を満たす次のタイムスタンプを返します。

コードは次のとおりです。

    create or replace type timestamp_table_type
    is
    table of timestamp;
    /

    create or replace function
     list_of_dates (
       calendar_string varchar2,
       start_date      TIMESTAMP WITH TIME ZONE,
       stop_date       TIMESTAMP WITH TIME ZONE)
    return
      timestamp_table_type
    pipelined
    is
      l_return_date_after TIMESTAMP WITH TIME ZONE := start_date - interval '1' second;
      l_next_run_date     TIMESTAMP WITH TIME ZONE;
    begin
      loop
        DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING(  
          calendar_string   => list_of_dates.calendar_string,
          start_date        => list_of_dates.start_date,
          return_date_after => l_return_date_after,
          next_run_date     => l_next_run_date);
          exit when list_of_dates.l_next_run_date > coalesce(list_of_dates.stop_date,date '9999-12-31');
          pipe row (list_of_dates.l_next_run_date);
          list_of_dates.l_return_date_after    := list_of_dates.l_next_run_date;
     end loop;
    end;
    /

毎月第 3 金曜日は次のようになると思います。

    begin
     dbms_scheduler.create_schedule(
     schedule_name => 'THIRD_THU_OF_EVERY_MONTH',
     repeat_interval => 'FREQ=MONTHLY;BYDAY=5;BYSETPOS=3');
    end;
    /

    select *
    from   table(
      list_of_dates(
        'THIRD_THU_OF_EVERY_MONTH',
        sysdate    ,
        null));

残念ながら、これをテストするのに便利な Oracle システムが手元にありません。

于 2013-01-30T12:05:21.517 に答える