スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

PL/pgSQLで日付の重なりを調べる

PostgreSQLには日付の重なりを調べるために、ORVERLAPS演算子があります。

SELECT ('2010-02-01'::timestamp, '2010-02-10'::timestamp)
OVERLAPS ('2010-02-05'::timestamp, '2010-02-20'::timestamp)
→true

これだけだと、単機能すぎるので色々機能を付加したPL/pgSQLの関数を作成します。
追加した機能は以下の通りです。
1. 開始点がnullの時は無限小とする
2. 終了点がnullの時は無限大とする
3. 区間内で反転しているかチェック
4. 最初の終点と次の開始点が一致している場合にtrueとする
3,4はオプションとして、引数で制御できます。デフォルトでは有効になっています。


CREATE OR REPLACE FUNCTION uv_is_overlap(
p_start_ts1 timestamp with time zone
,p_end_ts1 timestamp with time zone
,p_start_ts2 timestamp with time zone
,p_end_ts2 timestamp with time zone
,p_close_check boolean DEFAULT true
,p_check_reverse boolean DEFAULT true
) RETURNS boolean AS $$
DECLARE
w_start_ts1 timestamp with time zone := COALESCE(p_start_ts1, '-infinity');
w_end_ts1 timestamp with time zone := COALESCE(p_end_ts1, 'infinity');
w_start_ts2 timestamp with time zone := COALESCE(p_start_ts2, '-infinity');
w_end_ts2 timestamp with time zone := COALESCE(p_end_ts2, 'infinity');
BEGIN
IF p_check_reverse AND (w_start_ts1 > w_end_ts1 OR w_start_ts2 > w_end_ts2) THEN
RETURN false;
ELSIF (w_start_ts1, w_end_ts1) OVERLAPS (w_start_ts2, w_end_ts2) THEN
RETURN true;
ELSIF p_close_check AND (p_end_ts1 = p_start_ts2 OR p_end_ts2 = p_start_ts1) THEN
RETURN true;
ELSE
RETURN false;
END IF;
END;
$$ LANGUAGE plpgsql;

一行入魂サイトにまとめがあります。

追記2010/02/18 19:20
終点と始点で重なるチェックを片側しかやっていなかったので、両方チェックするように修正
スポンサーサイト

COMMENTS

COMMENT FORM

TRACKBACK


この記事にトラックバックする(FC2ブログユーザー)

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。