範囲型を試してみる

9.2からの新機能 range typeを試してみました。

テーブル作成

create table range_sample(
	int_range       int4range,
	bigint_range    int8range,
	mumeric_range   numrange,
	timestamp_range tsrange,
	date_range      daterange
);

データ登録

INSERT INTO range_sample VALUES(
'[1,     10)',
'[100,   1000)',
'[100.0, 100.99)',
'[2012-09-14 15:00:00, 2012-09-14 23:59:59)',
'[2012-09-14, 2012-12-31]'
);

「()」は対象の数を「含まない」、「[]」は対象の数を「含む」という扱いのようです。

素直にselectを発行

select * from range_sample ;
 int_range | bigint_range | mumeric_range  |                timestamp_range                |       date_range
-----------+--------------+----------------+-----------------------------------------------+-------------------------
 [1,10)    | [100,1000)   | [100.0,100.99) | ["2012-09-14 15:00:00","2012-09-14 23:59:59") | [2012-09-14,2013-01-01)
(1 row)

&& 演算子で範囲が重なっていたら真のようなので、
「対象の数値が範囲に含まれているか?」を問い合わせてみる

select * from range_sample where int_range && '[9,9]';
 int_range | bigint_range | mumeric_range  |                timestamp_range                |       date_range
-----------+--------------+----------------+-----------------------------------------------+-------------------------
 [1,10)    | [100,1000)   | [100.0,100.99) | ["2012-09-14 15:00:00","2012-09-14 23:59:59") | [2012-09-14,2013-01-01)
(1 row)

「9」を含むので、レコードが返ってくる。「10」は、、、

select * from range_sample where int_range && '[10,10]';
 int_range | bigint_range | mumeric_range | timestamp_range | date_range
-----------+--------------+---------------+-----------------+------------
(0 rows)

含まないので、返ってこない

対象の日が含まれるか?も同様で

select * from range_sample where date_range && '[2012-09-16,2012-09-16]';
 int_range | bigint_range | mumeric_range  |                timestamp_range                |       date_range
-----------+--------------+----------------+-----------------------------------------------+-------------------------
 [1,10)    | [100,1000)   | [100.0,100.99) | ["2012-09-14 15:00:00","2012-09-14 23:59:59") | [2012-09-14,2013-01-01)
(1 row)

select * from range_sample where date_range && '[2016-09-16,2016-09-16]';
 int_range | bigint_range | mumeric_range | timestamp_range | date_range
-----------+--------------+---------------+-----------------+------------
(0 rows)

おまけ explain

 explain analyze select * from range_sample where int_range && '[9,9]';
                                               QUERY PLAN
---------------------------------------------------------------------------------------------------------
 Seq Scan on range_sample  (cost=0.00..15.25 rows=2 width=160) (actual time=0.016..0.018 rows=1 loops=1)
   Filter: (int_range && '[9,10)'::int4range)
 Total runtime: 0.048 ms

今度、インデックスを貼ってみる