9

以下のクエリの結果を参照してください。

>> SELECT ADD_MONTHS(TO_DATE('30-MAR-11','DD-MON-RR'),-4) FROM DUAL;
30-NOV-10


>> SELECT ADD_MONTHS(TO_DATE('30-NOV-10','DD-MON-RR'),4) FROM DUAL;
31-MAR-11

ある日付に 4 か月を追加すると、「30-MAR-11」を取得するにはどうすればよいですか?

助けてください。

4

10 に答える 10

9

ここにOracle と Javaに関する別の質問があります

それは次のように述べています

add_months の Oracle リファレンスからhttp://download-west.oracle.com/docs/cd/B19306_01/server.102/b14200/functions004.htm

date が月の最終日である場合、または結果の月の日数が date の日部分よりも少ない場合、結果は結果の月の最終日になります。それ以外の場合、結果は日付と同じ日コンポーネントになります。

したがって、関数の動作を変更するには、開始日と終了日を手動で確認する必要があると思います。または、月の代わりに日を追加することもできます。add_day(しかし、refに関数が見つかりませんでした)

于 2011-03-18T07:46:14.350 に答える
5

回避策として、次のアルゴリズムを使用する可能性があります。

  1. TargetDate1を使用して目標日を計算しADD_MONTHSます。
  2. TargetDate2または、次のように目標日を計算します。

    1)ADD_MONTHSソース日付の月の最初に適用されます。
    2) ソース日付と同じ月の初めの間の日数の差を追加します。

  3. とのLEAST間でを選択します。TargetDate1TargetDate2

したがって、最終的に、ソース日付の日コンポーネントがターゲット月の日数よりも大きい場合、ターゲット日付には異なる日コンポーネントが含まれます。この場合、対象日は該当月の末日となります。

Oracle の SQL 構文に関する私の知識についてはよくわかりませんが、基本的に実装は次のようになります。

SELECT
  LEAST(
    ADD_MONTHS(SourceDate, Months),
    ADD_MONTHS(TRUNC(SourceDate, 'MONTH'), Months)
      + (SourceDate - TRUNC(SourceDate, 'MONTH'))
  ) AS TargetDate
FROM (
  SELECT
    TO_DATE('30-NOV-10', 'DD-MON-RR') AS SourceDate,
    4 AS Months
  FROM DUAL
)

この方法がどのように機能するかの詳細な図を次に示します。

SourceDate = '30-NOV-10'
Months     = 4

TargetDate1 = ADD_MONTHS('30-NOV-10', 4) = '31-MAR-11'  /* unacceptable */
TargetDate2 = ADD_MONTHS('01-NOV-10', 4) + (30 - 1)
            = '01-MAR-11' + 29 = '30-MAR-11'            /* acceptable */
TargetDate  = LEAST('31-MAR-11', '30-MAR-11') = '30-MAR-11'

また、さまざまなケースを示すいくつかの例を次に示します。

SourceDate | Months | TargetDate1 | TargetDate2 | TargetDate
-----------+--------+-------------+-------------+-----------
 29-NOV-10 |    4   |   29-MAR-11 |   29-MAR-11 |  29-MAR-11
 30-MAR-11 |   -4   |   30-NOV-10 |   30-NOV-10 |  30-NOV-10
 31-MAR-11 |   -4   |   30-NOV-10 |   01-DEC-10 |  30-NOV-10
 30-NOV-10 |    3   |   28-FEB-11 |   02-MAR-11 |  28-FEB-11
于 2011-03-18T10:01:28.483 に答える
3

区間演算を使用して、必要な結果を得ることができます

SQL> select date '2011-03-30' - interval '4' month
  2    from dual;

DATE'2011
---------
30-NOV-10

SQL> ed
Wrote file afiedt.buf

  1  select date '2010-11-30' + interval '4' month
  2*   from dual
SQL> /

DATE'2010
---------
30-MAR-11

ただし、すべての月に存在しない日を扱う場合、間隔演算には落とし穴があることに注意してください。

SQL> ed
Wrote file afiedt.buf

  1  select date '2011-03-31' + interval '1' month
  2*   from dual
SQL> /
select date '2011-03-31' + interval '1' month
                         *
ERROR at line 1:
ORA-01839: date not valid for month specified
于 2011-04-01T07:16:51.413 に答える
1

このようなものはどうですか:

SELECT
    LEAST(
        ADD_MONTHS(TO_DATE('30-MAR-11','DD-MON-RR'),-4),
        ADD_MONTHS(TO_DATE('30-MAR-11','DD-MON-RR')-1,-4)+1
    )
FROM
    DUAL
;

結果:2010年11月30日

SELECT
    LEAST(
        ADD_MONTHS(TO_DATE('30-NOV-10','DD-MON-RR'),4),
        ADD_MONTHS(TO_DATE('30-NOV-10','DD-MON-RR')-1,4)+1
    )
FROM
    DUAL
;

結果:2011年3月30日

于 2013-02-15T16:42:01.237 に答える
0

簡単な解決策:

ADD_MONTHS(date - 1, x) + 1
于 2015-08-05T13:23:26.907 に答える
0

このadd_months関数は、日付に n か月を加えた値を返します。

11 月 30 日はその月の最後の日なので、4 か月を足すと 4 か月の終わりの日付になります。これは予期される動作です。日付が変更されない場合は、回避策として、新しい日付が返されてから 1 日後を減算します。

SQL> SELECT ADD_MONTHS(TO_DATE('30-NOV-10','DD-MON-RR'),4) -1 from dual;

ADD_MONTH
---------
30-MAR-11
于 2011-03-18T07:46:29.513 に答える
0
SELECT TO_DATE('30-NOV-10','DD-MON-RR') + 
       (
        ADD_MONTHS(TRUNC(TO_DATE('30-NOV-10','DD-MON-RR'),'MM'),4) - 
        TRUNC(TO_DATE('30-NOV-10','DD-MON-RR'),'MM')
       ) RESULT
  FROM DUAL;

括弧内のこのセクション:

ADD_MONTHS(TRUNC(TO_DATE('30-NOV-10','DD-MON-RR'),'MM'),4) - TRUNC(TO_DATE('30-NOV-10','DD-MON-RR'),'MM')

入力した日付から 4 か月後までの日数を示します。したがって、この日数を指定した日付に追加すると、4 か月後の正確な日付が得られます。

参照: http://www.dba-oracle.com/t_test_data_date_generation_sql.htm

于 2011-03-19T15:52:34.243 に答える
-1
    CREATE OR REPLACE FUNCTION My_Add_Month(
      STARTDATE           DATE,
      MONTHS_TO_ADD      NUMBER
    )
        RETURN DATE
    IS
        MY_ADD_MONTH_RESULT DATE;
    BEGIN

        SELECT ORACLES_ADD_MONTH_RESULT + NET_DAYS_TO_ADJUST INTO MY_ADD_MONTH_RESULT FROM
        (
            SELECT T.*,CASE WHEN SUBSTRACT_DAYS > ADD_DAYS THEN ADD_DAYS - SUBSTRACT_DAYS ELSE 0 END AS NET_DAYS_TO_ADJUST FROM
            (
                SELECT T.*,EXTRACT(DAY FROM ORACLES_ADD_MONTH_RESULT) AS SUBSTRACT_DAYS FROM
                (
                    SELECT ADD_MONTHS(STARTDATE,MONTHS_TO_ADD) AS ORACLES_ADD_MONTH_RESULT,EXTRACT(DAY FROM STARTDATE) AS ADD_DAYS FROM DUAL
                )T
            )T
        )T;
        RETURN TRUNC(MY_ADD_MONTH_RESULT);
    END My_Add_Month;
    /

    --test & verification of logic & function both
    SELECT T.*,ORACLES_ADD_MONTH_RESULT + NET_DAYS_TO_ADJUST AS MY_ADD_MONTH_RESULT,
    My_Add_Month(STARTDATE,MONTHS_TO_ADD) MY_ADD_MONTH_FUNCTION_RESULT
    FROM
    (
        SELECT T.*,CASE WHEN SUBSTRACT_DAYS > ADD_DAYS THEN ADD_DAYS - SUBSTRACT_DAYS ELSE 0 END AS NET_DAYS_TO_ADJUST FROM
        (
            SELECT T.*,EXTRACT(DAY FROM ORACLES_ADD_MONTH_RESULT) AS SUBSTRACT_DAYS FROM
            (
                SELECT T.*,ADD_MONTHS(STARTDATE,MONTHS_TO_ADD) AS ORACLES_ADD_MONTH_RESULT,EXTRACT(DAY FROM STARTDATE) AS ADD_DAYS FROM
                (
                    SELECT TO_DATE('28/02/2014','DD/MM/YYYY') AS STARTDATE, 1 AS MONTHS_TO_ADD FROM DUAL
                )T
            )T
        )T
    )T;        

クエリ結果

開始日 2014 年 2 月 28 日

MONTHS_TO_ADD 1

ORACLES_ADD_MONTH_RESULT 2014 年 3 月 31

ADD_DAYS 28

SUBSTRACT_DAYS 31

NET_DAYS_TO_ADJUST -3

MY_ADD_MONTH_RESULT 2014 年 3 月 28 日

MY_ADD_MONTH_FUNCTION_RESULT 2014 年 3 月 28 日

于 2014-04-30T19:21:28.387 に答える