0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Oracle Database 26ai) Calendar 関数を試してみた (2026/05/04)

0
Posted at

はじめに

Oracle AI Database 26ai(バージョン 23.26.1 以降)では、日付演算を扱う Calendar 関数が新たに導入されました。従来から TRUNCADD_MONTHSTO_CHAREXTRACT などの関数を組み合わせることで日付演算は可能でしたが、コードが煩雑になりやすく、関数ごとに挙動が微妙に異なる点が課題でした。

新しい Calendar 関数群は、こうした日付演算をシンプルかつ一貫した形で記述できるように設計されています。年・四半期・月・週・日といった時間階層ごとに対称的な関数セットが用意されており、直感的に利用できます。また、NLS(National Language Support)設定に連動しているため、多言語対応のシステムでも扱いやすいという特徴があります。

Calendar 関数は大きく 4 種類のカテゴリに分類されます。

カテゴリ 代表的な関数 戻り値の型 概要
Calendar Format String CALENDAR_YEAR, CALENDAR_QUARTER, CALENDAR_MONTH, CALENDAR_WEEK, CALENDAR_DAY VARCHAR2 日付から各期間の文字列表現を返す
Calendar Add Periods CALENDAR_ADD_YEARS, CALENDAR_ADD_QUARTERS, CALENDAR_ADD_MONTHS, CALENDAR_ADD_WEEKS, CALENDAR_ADD_DAYS DATE 指定した期間数を加算した日付を返す(負値で過去も可)
Calendar Start/End Date CALENDAR_YEAR_START_DATE, CALENDAR_YEAR_END_DATE(四半期・月・週も同様) DATE 各期間の開始日・終了日を返す
Calendar Number CALENDAR_YEAR_NUMBER, CALENDAR_QUARTER_OF_YEAR, CALENDAR_MONTH_OF_YEAR(他多数) NUMBER 日付から各期間の数値を返す

Calendar 関数を組み合わせると、データウェアハウスで活用できるカレンダーディメンションテーブルを簡潔に作成できます。
なお、Calendar関数と同じ構成で Fiscal および Retail 向けの関数セットも用意されています(本記事では Gregorian カレンダーの関数のみ検証します)。

  • CALENDAR_* 関数(Gregorian カレンダー)の 4 カテゴリ
  • NLS 言語設定による出力変化の確認
  • カレンダーディメンションテーブルの作成

事前準備

  • Oracle AI Database 26ai(バージョン 23.26.1 以降)
  • Calendar 関数はすべての Oracle 26ai ユーザーが特別な権限なしに利用可能です

手順

Step 1: Calendar Start/End Date 関数

「今年の最初の日と最後の日を取得する」というシンプルなケースで、従来の方法と新しい方法を比較します。

従来の方法:

SELECT trunc(sysdate,'YYYY')                  AS first_day_of_year,
       add_months(trunc(sysdate,'YYYY'),12)-1 AS last_day_of_year;

Calendar 関数を使った方法:

SELECT calendar_year_start_date(sysdate) AS first_day_of_year,
       calendar_year_end_date(sysdate)   AS last_day_of_year;

実行結果(2026年5月4日時点):

FIRST_DAY_OF_YEAR LAST_DAY_OF_YEAR
26-01-01 26-12-31

CALENDAR_YEAR_START_DATE / CALENDAR_YEAR_END_DATE はいずれも DATE 型を引数に取り、DATE 型を返します。四半期・月・週にも同等の関数が用意されています。

SELECT calendar_year_start_date(date'2026-04-04')    AS year_start,
       calendar_year_end_date(date'2026-04-04')      AS year_end,
       calendar_quarter_start_date(date'2026-04-04') AS quarter_start,
       calendar_quarter_end_date(date'2026-04-04')   AS quarter_end,
       calendar_month_start_date(date'2026-04-04')   AS month_start,
       calendar_month_end_date(date'2026-04-04')     AS month_end,
       calendar_week_start_date(date'2026-04-04')    AS week_start,
       calendar_week_end_date(date'2026-04-04')      AS week_end;

実行結果:

YEAR_STA YEAR_END QUARTER_ QUARTER_ MONTH_ST MONTH_EN WEEK_STA WEEK_END
-------- -------- -------- -------- -------- -------- -------- --------
26-01-01 26-12-31 26-04-01 26-06-30 26-04-01 26-04-30 26-04-02 26-04-08

Step 2: Calendar Format String 関数

CALENDAR_YEARCALENDAR_QUARTERCALENDAR_MONTHCALENDAR_WEEKCALENDAR_DAY は日付を人間が読みやすい文字列に変換します。

SELECT calendar_year(date'2026-10-10')    AS cal_year,
       calendar_quarter(date'2026-10-10') AS cal_quarter,
       calendar_month(date'2026-10-10')   AS cal_month,
       calendar_week(date'2026-10-10')    AS cal_week,
       calendar_day(date'2026-10-10')     AS cal_day;

実行結果(セッションの言語が日本語の場合):

CAL_ CAL_QUA CAL_MONTH  CAL_WEEK CAL_DAY
---- ------- ---------- -------- -------------
2026 Q4-2026 10月-2026  W41-2026 10-10月-2026

NLS 言語の変更による出力の違い

これらの関数は NLS 設定に連動しています。セッションの言語を変更すると、月名や曜日名が自動的に翻訳されます。

英語に変更する場合:

ALTER SESSION SET nls_language = 'AMERICAN';

SELECT calendar_year(date'2026-10-10')    AS cal_year,
       calendar_quarter(date'2026-10-10') AS cal_quarter,
       calendar_month(date'2026-10-10')   AS cal_month,
       calendar_week(date'2026-10-10')    AS cal_week,
       calendar_day(date'2026-10-10')     AS cal_day;

実行結果(英語):

CAL_ CAL_QUA CAL_MONT CAL_WEEK CAL_DAY
---- ------- -------- -------- -----------
2026 Q4-2026 OCT-2026 W41-2026 10-OCT-2026

Step 3: Calendar Add Periods 関数

CALENDAR_ADD_YEARSCALENDAR_ADD_QUARTERSCALENDAR_ADD_MONTHSCALENDAR_ADD_WEEKSCALENDAR_ADD_DAYS を使うと、特定の期間を加減算した日付を返せます。負の値を指定すると過去の日付を取得できます。

SELECT calendar_add_years(sysdate,  1) AS today_in_one_year,
       calendar_add_years(sysdate,  2) AS today_in_two_years,
       calendar_add_days (sysdate,  1) AS tomorrow,
       calendar_add_days (sysdate, -1) AS yesterday;

実行結果(2026年5月4日時点):

TODAY_IN TODAY_IN TOMORROW YESTERDA
-------- -------- -------- --------
27-05-04 28-05-04 26-05-05 26-05-03

従来の ADD_MONTHS は月・年の加算に対応していましたが、週・日の加算には別途計算が必要でした。Calendar 関数では時間階層ごとに専用の関数が提供されているため、コードの意図が明確になります。

Step 4: Calendar Number 関数

日付から数値を取得する方法も、従来の方法と比較してシンプルになりました。

従来の方法(TO_CHAR を使う場合):

SELECT to_number(to_char(sysdate, 'DD'))   AS day_number,
       to_number(to_char(sysdate, 'MM'))   AS month_number,
       to_number(to_char(sysdate, 'YYYY')) AS year_number;

従来の方法(EXTRACT を使う場合):

SELECT extract(day from sysdate)   AS day_number,
       extract(month from sysdate) AS month_number,
       extract(year from sysdate)  AS year_number;

新しい Calendar 関数を使った方法:

SELECT calendar_day_of_month(sysdate)  AS day_number,
       calendar_month_of_year(sysdate) AS month_number,
       calendar_year_number(sysdate)   AS year_number;

実行結果(2026年5月4日時点):

DAY_NUMBER MONTH_NUMBER YEAR_NUMBER
---------- ------------ -----------
         4            5        2026

Calendar Number 関数には以下の 9 種類が用意されています。

関数名 説明
CALENDAR_YEAR_NUMBER 年を数値で返す
CALENDAR_QUARTER_OF_YEAR 年内の四半期番号(1〜4)を返す
CALENDAR_MONTH_OF_YEAR 年内の月番号(1〜12)を返す
CALENDAR_MONTH_OF_QUARTER 四半期内の月番号(1〜3)を返す
CALENDAR_WEEK_OF_YEAR 年内の週番号を返す
CALENDAR_DAY_OF_YEAR 年内の日番号(1〜365/366)を返す
CALENDAR_DAY_OF_QUARTER 四半期内の日番号を返す
CALENDAR_DAY_OF_MONTH 月内の日番号(1〜31)を返す
CALENDAR_DAY_OF_WEEK 週内の曜日番号を返す

Step 5: カレンダーディメンションテーブルを作成

Calendar 関数を組み合わせると、データウェアハウスで必要なカレンダーディメンションテーブルを簡潔に構築できます。以下の例では、現在日時を基準に前後 2 年分のデータを生成します。

CREATE TABLE IF NOT EXISTS dim_calendar AS
WITH date_interval AS (
    SELECT calendar_year_start_date
               (calendar_add_years(sysdate, -2)) AS start_date,
           calendar_year_end_date
               (calendar_add_years(sysdate,  2)) AS end_date
),
date_generator AS (
    SELECT calendar_add_days(start_date, rownum-1) AS d
      FROM date_interval
    CONNECT BY rownum-1 <= end_date - start_date
)
SELECT d                               AS dim_calendar_key,
       d                               AS cal_date,
       calendar_day(d)                 AS cal_day,
       calendar_week(d)                AS cal_week,
       calendar_week_start_date(d)     AS cal_week_start_date,
       calendar_week_end_date(d)       AS cal_week_end_date,
       calendar_month(d)               AS cal_month,
       calendar_month_start_date(d)    AS cal_month_start_date,
       calendar_month_end_date(d)      AS cal_month_end_date,
       calendar_quarter(d)             AS cal_quarter,
       calendar_quarter_start_date(d)  AS cal_quarter_start_date,
       calendar_quarter_end_date(d)    AS cal_quarter_end_date,
       calendar_year(d)                AS cal_year,
       calendar_year_start_date(d)     AS cal_year_start_date,
       calendar_year_end_date(d)       AS cal_year_end_date
  FROM date_generator;

注意: CONNECT BY rownum-1 <= end_date - start_dateend_date - start_date は DATE 型同士の減算で日数差を返します。生成される行数は 5 年分で約 1,826 行です。

作成されたテーブルの内容を確認します:

SELECT * FROM dim_calendar
WHERE cal_month = calendar_month(sysdate) and rownum < 4
ORDER BY cal_date;
DIM_CALE CAL_DATE CAL_DAY               CAL_WEEK  CAL_WEEK CAL_WEEK
-------- -------- --------------------- --------- -------- --------
CAL_MONTH          CAL_MONT CAL_MONT CAL_QUAR CAL_QUAR CAL_QUAR CAL_Y CAL_YEAR
------------------ -------- -------- -------- -------- -------- ----- --------
CAL_YEAR
--------
26-05-01 26-05-01 01-MAY-2026           W18-2026  26-04-30 26-05-06
MAY-2026           26-05-01 26-05-31 Q2-2026  26-04-01 26-06-30 2026  26-01-01
26-12-31

26-05-02 26-05-02 02-MAY-2026           W18-2026  26-04-30 26-05-06
MAY-2026           26-05-01 26-05-31 Q2-2026  26-04-01 26-06-30 2026  26-01-01
26-12-31

26-05-03 26-05-03 03-MAY-2026           W18-2026  26-04-30 26-05-06
MAY-2026           26-05-01 26-05-31 Q2-2026  26-04-01 26-06-30 2026  26-01-01
26-12-31

クリーンアップ

検証が完了したらテーブルを削除します。

DROP TABLE IF EXISTS dim_calendar;

おわりに

今回の検証で確認できたポイントをまとめます。

  • 可読性の向上: 従来の TRUNCADD_MONTHSTO_CHAR などの組み合わせに比べ、Calendar 関数は意図が明確で読みやすいコードになります。
  • 一貫性のある API 設計: 年・四半期・月・週・日という時間階層ごとに対称的な関数セットが提供されており、覚えやすく使いやすい設計になっています。
  • NLS 対応: CALENDAR_YEARCALENDAR_MONTH などの文字列関数はセッションの NLS 設定に連動し、多言語対応のシステムでも自然に動作します。
  • データウェアハウス用途に最適: カレンダーディメンションテーブルの作成など、時間軸を必要とするデータ分析基盤の構築がよりシンプルに記述できます。

Gregorian カレンダー以外にも Fiscal・Retail カレンダー向けの関数セットが用意されているため、会計・小売業などのドメインでも幅広く活用できます。

参考情報

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?