集合を返す関数 generate_series
PostgreSQLには、8.0 から集合を返す関数というのがある。
8.0 時点では、generate_series が唯一みたいだけど。
startからstopまでの連番を1(またはstep)刻みで生成します。
step には負の値を指定することも可能です。
今回はこの generate_series を7.4の時代に使いたくて自作したので、そのことについて書いてみる。
8.0 時点では、generate_series が唯一みたいだけど。
generate_series( start, stop )
generate_series( start, stop, step )startからstopまでの連番を1(またはstep)刻みで生成します。
step には負の値を指定することも可能です。
select * from generate_series( 1, 5 );
generate_series
---------------------
1
2
3
4
5今回はこの generate_series を7.4の時代に使いたくて自作したので、そのことについて書いてみる。
まず、generate_series の使いどころ。
PostgreSQLのマニュアルにも書かれているけど、任意の日付の何日おきの日付を取得するとか。
自分の場合は、generate_series で月の初日(1)から月の最後(8月なら31)までの日付を生成し、
テーブルに格納されているデータを join する。
データがない日は日付だけでそれ以外はNULLな行になった日付と関連付いたデータを取得できる。
例えば、以下のような schedule テーブルがあったとする。
で、SQL文とその結果。
まぁ連番があれば、他にもいろいろと便利なことは多い。
で、自作したわけです。
旧 PostgreSQL 以外にも、MySQL とか Oracle とかでも使えるとおもう。
ただし、PostgreSQL でしか確認していないので、他の環境では保証できないです。
8.0 にバージョンアップしたときに、組み込み関数とバッティングしないように、generate_series_mine という関数名にしています。
まぁたいしたことはやってないので、見ればわかるんじゃないかと。
もし見ている方で解説欲しい方がいればコメントいただければ解説します。
なお、組み込み関数と同じ状態にするには、引数と戻り値、内部で使う cnt の定義を bigint にしたものも定義しないといけない。
また、それぞれに第三の引数を設定し、10行目を
参考文献
『PostgreSQL 8.0.0 文書 9.18. 集合を返す関数』
PostgreSQLのマニュアルにも書かれているけど、任意の日付の何日おきの日付を取得するとか。
自分の場合は、generate_series で月の初日(1)から月の最後(8月なら31)までの日付を生成し、
テーブルに格納されているデータを join する。
データがない日は日付だけでそれ以外はNULLな行になった日付と関連付いたデータを取得できる。
例えば、以下のような schedule テーブルがあったとする。
sdate schedule
-----------------------
2007-08-01 買い物
2007-08-03 休み
2007-08-04 買い物で、SQL文とその結果。
select day,schedule
from ( select * generate_series(1,5) as day ) base
left outer join (select * from schedule) t1
on base.day=extract(day from t1.sdate)
order by base.day;
day schedule
----------------------------
1 買い物
2
3 休み
4 買い物
5まぁ連番があれば、他にもいろいろと便利なことは多い。
で、自作したわけです。
旧 PostgreSQL 以外にも、MySQL とか Oracle とかでも使えるとおもう。
ただし、PostgreSQL でしか確認していないので、他の環境では保証できないです。
CREATE FUNCTION generate_series_mine(integer, integer) RETURNS SETOF integer
AS '
DECLARE
maxcnt ALIAS FOR $2 ;
cnt integer ;
BEGIN
cnt := $1 ;
WHILE cnt <= maxcnt LOOP
RETURN NEXT cnt ;
cnt := cnt + 1 ;
END LOOP;
RETURN ;
END;
'
LANGUAGE plpgsql;8.0 にバージョンアップしたときに、組み込み関数とバッティングしないように、generate_series_mine という関数名にしています。
まぁたいしたことはやってないので、見ればわかるんじゃないかと。
もし見ている方で解説欲しい方がいればコメントいただければ解説します。
なお、組み込み関数と同じ状態にするには、引数と戻り値、内部で使う cnt の定義を bigint にしたものも定義しないといけない。
また、それぞれに第三の引数を設定し、10行目を
cnt := cnt + 第三引数 ;にしたものも定義しないといけないです。
参考文献
『PostgreSQL 8.0.0 文書 9.18. 集合を返す関数』
カテゴリ:
PostgreSQL
トラックバック
このブログ記事に対するトラックバックURL
http://fakelife.info/mt/system/mt-tb.cgi/22
コメントする