3. 20から30までの自然数を出力
次は、再帰のあるwith
句の構文に慣れておきましょう。例として、20から30までの自然数を出力してみます。下記のようにgenerate_series
関数を使えばいいのですが、あえて再帰SQLで求めてみます。
select Val from generate_series(20,30) as tmp(Val);
Val |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
再帰SQLを使う方法は次のとおりです。なお、再帰のあるwith
句では、with
の直後のrecursive
キーワードが必須となります。
with recursive rec(Val) as( select 20 union all select Val+1 from rec where Val+1 <=30) select Val from rec;
select 20
を実行して、select Val+1 from (前回のselect文の結果(20)) where Val+1 <=30
を実行して、 select Val+1 from (前回のselect文の結果(21)) where Val+1 <=30
を実行して、…
…
(以下select
文の結果が空集合になるまで続く)といった処理を行ってると理解しておけばいいでしょう。select Val+1 from rec where Val+1 <=30
のfrom
句のrecは、前回のselect
文の結果となるのです。
4. フィボナッチ数列を求める
次はフィボナッチ数列を求めてみます。フィボナッチ数列は、1項目が0、2項目が1、3項目以降は前の2項の和となる数列で、「0, 1, 1, 2, 3, 5, 8, 13, 21,……」といったものです。
with recursive rec(N3,N2,N1) as( select 1,1,0 union all select N3+N2,N3,N2 from rec) select * from rec Limit 15;
N3 | N2 | N1 |
1 | 1 | 0 |
2 | 1 | 1 |
3 | 2 | 1 |
5 | 3 | 2 |
8 | 5 | 3 |
13 | 8 | 5 |
21 | 13 | 8 |
34 | 21 | 13 |
55 | 34 | 21 |
89 | 55 | 34 |
144 | 89 | 55 |
233 | 144 | 89 |
377 | 233 | 144 |
610 | 377 | 233 |
987 | 610 | 377 |
最初のselect 1,1,0
で、最初のフィボナッチ数を求めてます。
次の、select N3+N2,N3,N2 from rec
で、1つ前の項と2つ前の項の和をN3+N2
として求めてます。そして、次のフィボナッチ数の計算に使用するので、前のselect
文の結果のN3をN2に移して、前のselect
文の結果のN2をN1に移してます。最後に、with
句の外側のselect
文でLimit 15
を指定して、再帰SQLの結果の行数を15行に制限してます。
最後に
本稿では、再帰SQLの構文などを扱いました。次回は、最小日からの最大日までの補完や、空き番号一覧の作成を扱います。
参考資料
- 新しい業界標準「SQL99」詳細解説
再帰SQLに関する説明です。
- [PostgreSQLウォッチ]第39回 PostgreSQL 8.4の新機能「再帰SQL」と最新情報
再帰SQLに関する説明です。
- 再帰SQL --- Let's Postgres
再帰SQLに関する説明です。
- 7.8. WITH問い合わせ
PostgreSQLのマニュアルです。WITH問い合わせに関する説明です。