何となく雑多なメモです。使用したPostgreSQLのバージョンは9.5.2。
(1)10進数との乗除算ができる
select interval '1minute' * 100;
+----------+
| ?column? |
+----------+
| 01:40:00 |
+----------+
-- 100 minutes -> 1 hour and 40 minutes
select interval '1day' / 5;
+----------+
| ?column? |
+----------+
| 04:48:00 |
+----------+
-- 1 / 5 day -> 4 hour and 48 minutes
日付・時刻型との加減算に比べて余り使わないけど。また乗算は、わざわざ使わなくても ↓ のように定義すれば済みますが、割り算は結構便利。
select interval '100minute';
+----------+
| ?column? |
+----------+
| 01:40:00 |
+----------+
(2)定義する書式が柔軟
select interval '100minute', -- 単位が単数形, 空白なし
interval '100 minute', -- 〃 空白あり
interval '100minutes', -- 単位が複数形, 空白なし
interval '100 minutes'; -- 〃 空白あり
+----------+
| ?column? |
+----------+
| 01:40:00 |
+----------+
基本的に「数値 + 時間の単位」で入力します。その書き方で融通が効いてて楽。単数・複数も区別しないという、文法的には変だけど。1 hours と書いても通ります。
(3)日付・時刻型との減算で、intervalと明示しないとエラー
select now() + '1 month', -- 1ヶ月後
now() - interval '1 month'; -- 1ヶ月前
+-------------------------------+-------------------------------+
| ?column? | ?column? |
+-------------------------------+-------------------------------+
| 2016-07-16 20:35:15.368672+09 | 2016-05-16 20:35:15.368672+09 |
+-------------------------------+-------------------------------+
(1 row)
select now() - '1 month'; -- 減算ではinterval省けない
ERROR: invalid input syntax for type timestamp with time zone:
"1 month" at character 16
STATEMENT: select now() - '1 month';
ERROR: invalid input syntax for type timestamp with time zone:
"1 month"
LINE 1: select now() - '1 month';
^
これは不便というか、最近ちょっと嵌った点。足し算は + だけで通るので減算も同じだと思い込んでました。マイナスのIntervalもあるので ↓ 区別するためかな。
select -'1 day' :: interval;
+----------+
| ?column? |
+----------+
| -1 days |
+----------+
(1 row)
(4)10進数の時間単位に変換するのは、自前で工夫
select
date_trunc('hour', intv),
extract(hour from intv),
justify_hours(intv)
from cast('0:59:59' as interval) as intv
-- ほぼ1時間なので、10進数にして丸めたいが、適当な関数がない
;
+------------+-----------+---------------+
| date_trunc | date_part | justify_hours |
+------------+-----------+---------------+
| 00:00:00 | 0 | 00:59:59 |
+------------+-----------+---------------+
(1 row)
select extract(epoch from intv)
/ extract(epoch from interval '1hour')
from cast('0:59:59' as interval) as intv
-- いったん秒に変換して、当該単位の秒数で割れば10進数
;
+-------------------+
| ?column? |
+-------------------+
| 0.999722222222222 |
+-------------------+
(1 row)
もしかして何か関数があるかもしれないけど、今のところ不明。例えば1時間おきに機械で測ったデータがあり、測定間隔が正常か確認する、で隣接する2データの時間差をウィンドウ関数で出して見るような時。数秒くらい1時間に足りない or 超えるものは丸めると便利ですが、適当な関数がない。
で、上のようにintervalを秒に変換(extract…epoch)、当該時間の秒数で割って10進数にし、必要に応じて丸めます。要するに秒数どうしの演算。式一つで済むから大ごとじゃないけど、ちょっと分かりづらいのでストアド化するといいかも。…って昨日も書いた気が (-_-;)