【PostgreSQL】generate_series 連続データを生成できる名関数

✅ はじめに

PostgreSQLを使っていると、「毎日のデータを出したいけど、データが存在しない日は結果が出ない」「グラフ用に日付の連番がほしい」といった場面に出くわすことがあります。

そんなときに大活躍するのが、PostgreSQLの隠れた名関数 generate_series() です。
この関数を使えば、連番や日付、時刻といった連続データをSQLだけで簡単に生成することができます。この記事では、generate_series()の基本から応用まで、実用的な使い方を解説します。


■ generate_series()とは?

generate_series() は、PostgreSQLに組み込まれているテーブル関数で、連続した値を行として返す機能を持っています。

主な用途

  • 数値の連番生成
  • 日付や時刻の連続データ生成
  • 欠損値補完やベースとなる集計軸の作成

■ 基本構文と使い方の例(充実版)

1. 数値の連番を生成

SELECT generate_series(1, 10);

➡ 1〜10 の連番を1列で出力します。

2. ステップ(増分)を指定する

SELECT generate_series(0, 100, 10);

➡ 0, 10, 20, …, 100 のように、10刻みの連番を生成できます。

3. 列に別名をつけて扱いやすくする

SELECT generate_series(1, 5) AS id;

➡ 結果列に id という名前がつきます。
後でJOINや集計に使いやすくなります。

4. 1日ごとの日付を生成

SELECT generate_series(
  DATE '2024-01-01',
  DATE '2024-01-07',
  INTERVAL '1 day'
) AS day;

➡ 2024年1月1日から7日までの日付を1日刻みで生成します。

5. 毎時のタイムスタンプを生成

SELECT generate_series(
  TIMESTAMP '2024-01-01 08:00',
  TIMESTAMP '2024-01-01 20:00',
  INTERVAL '1 hour'
) AS hour;

➡ 08:00, 09:00, … 20:00 までの1時間ごとの時刻を生成。

6. 負の数や逆方向の連番も可能

SELECT generate_series(10, 0, -2) AS countdown;

➡ 10, 8, 6, …, 0 といったカウントダウン的な連番も可能です。

7. クロスJOINで多次元の組み合わせを生成

SELECT d, h
FROM generate_series(DATE '2024-05-01', DATE '2024-05-03', INTERVAL '1 day') AS d,
     generate_series(0, 23) AS h;

➡ 2024-05-01〜03 の各日付 × 0〜23時 を掛け合わせた72通りの組み合わせを生成(例:アクセスログ集計などに便利)

8. WITH句(共通テーブル式)での利用例

WITH days AS (
  SELECT generate_series(DATE '2024-01-01', DATE '2024-01-10', INTERVAL '1 day') AS day
)
SELECT day
FROM days
WHERE EXTRACT(DOW FROM day) IN (0, 6);  -- 土日だけ抽出

➡ 1月1日〜10日のうち、土日だけを抽出する例です。
WITH 句と組み合わせると、読みやすく再利用性も高くなります。

このように、generate_series() は数値・日付・時間だけでなく、クロスJOINや日付関数、WITH句と組み合わせて柔軟なSQL生成が可能です。


■ JOINで活きる!集計用ベーステーブルの生成

たとえば、ユーザーごとに「直近7日間のデータを日別に出したい」場合、日付が存在しない日は表示されません。これを解決するのが generate_series()

✔ ユーザー × 日付 の組み合わせを生成

SELECT u.user_id, g.day
FROM users u
JOIN generate_series(
  CURRENT_DATE - INTERVAL '6 days',
  CURRENT_DATE,
  INTERVAL '1 day'
) AS g(day) ON true;

→ 全ユーザーに対して7日間分の日付行を自動生成。
この上に LEFT JOIN で実データを乗せれば、「ゼロ件の日」も集計可能になります。


■ ユースケース例

シーン 活用内容
■ 棒グラフや折れ線グラフのX軸 日付や時間を抜けなく出したいときに便利
■ 集計レポート 「件数0」でも行が出てほしい場合のベーステーブル作成
■ テストデータ作成 一時的に1000件のシーケンスを作りたいとき
■ 時系列のギャップ検出 欠損している時間帯や日付を抽出する前処理にも使える

⚠ 注意点

  • 大きな範囲(例:100万件以上)を一気に生成すると重くなるため、上限には注意
  • generate_series() はPostgreSQL限定機能(MySQLやSQL Serverでは非対応)
  • 日付型とタイムスタンプ型を混在させると暗黙の型変換が起きることがある

■ まとめ

generate_series() は、PostgreSQLを使う上で「知っておいて損のない関数」です。

特に、以下のような場面では非常に役立ちます:

  • 連続したデータをループなしで生成したい
  • 「存在しない値」も出したいときの補完ベースが必要
  • 時系列やレポート出力でX軸を揃えたい

SQLだけでこれを実現できるのは、PostgreSQLの大きな強みです。
使い方に慣れれば、SQLの表現力は一段と広がります!


■ 関連キーワード

  • PostgreSQL generate_series 使い方
  • PostgreSQL 連番生成
  • SQL 日付補完
  • SQL グラフ 日付軸
  • テーブル関数 generate_series
  • PostgreSQL 欠損日付を埋める
  • 0件の日も表示したい SQL