LoginSignup
6
6

More than 5 years have passed since last update.

PostgreSQLの範囲型で期間の重複をチェックするミニサンプル

Last updated at Posted at 2014-11-03

経緯

「パラメータで渡す開始日時・終了日時の期間が、テーブルのtimestamp型のカラムに入っている開始日時・終了日時の期間と重複しているか確認するSQLを書きたいんですが...」

(これ、PostgreSQL勉強会@札幌でやったとこだ!)

というわけでミニサンプル書いておく。

ミニサンプル

やりたいこと

create table bar (
    bar_id bigserial,
    open_at timestamp without time zone,
    close_at timestamp without time zone,
    primary key (bar_id)
);
-- 10月1日0時(以上)から10月2日0時(未満)を比較対象に見立てる
insert into bar(open_at, close_at) 
values ('2014-10-01 00:00:00', '2014-10-02 00:00:00' );

こんなテーブルがあったときに、パラメータで渡される他のopen_at, close_atと重複しているレコードがあるかどうか調べたい。

方法

tsrange関数で、レコードとパラメータを範囲型に変換して、&&演算子で比較する方法が一番わかりやすいかなと思う。

-- 9月30日12時から10月1日0時までの重複を確認(重複しない想定)
select name 
from (
  select bar_id, strange (open_at, close_at, '[)') as range from bar
) as A
where range && tsrange('2014-09-30 12:00:00'::timestamp, '2014-10-01 00:00:00'::timestamp, '[)')

-- 9月30日12時から10月1日12時までの重複を確認(重複する想定)
select bar_id
from (select bar_id, tsrange(open_at, close_at, '[)') as range from bar) as A
where range && tsrange('2014-09-30 12:00:00'::timestamp, '2014-10-01 12:00:00'::timestamp, '[)')

-- 10月1日0時から10月2日12時までの重複を確認(重複する想定)
select bar_id
from (select bar_id, tsrange(open_at, close_at, '[)') as range from bar) as A
where range && tsrange('2014-10-01 00:00:00'::timestamp, '2014-10-02 12:00:00'::timestamp, '[)')

-- 10月2日0時から10月2日12時までの重複を確認(重複しない想定)
select bar_id
from (select bar_id, tsrange(open_at, close_at, '[)') as range from bar) as A
where range && tsrange('2014-10-02 00:00:00'::timestamp, '2014-10-02 12:00:00'::timestamp, '[)')

重複があればbar_idカラムの値が検索される。

今回は open_at以上〜close_at未満で比較したいので、境界値は'[)'を利用しているけれども、境界値を変更すると、もちろん重複結果も変えることができる。

参考文献

範囲型の説明は以下が詳しい。

6
6
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
6
6