YAMAGUCHI::weblog

海水パンツとゴーグルで、巨万の富を築きました。カリブの怪物、フリーアルバイター瞳です。

部分フィールドの抽出

詳しくは書けないが、たとえば以下のようなテーブルがあったとする。

term_start  date
term_end    date
number      int

このterm_startとterm_endをみて、case文をクエリに書こうとするときにdate型とinterval型を混ぜて演算させると、戻り値がinterval型になってしまう。一方date型同士で純粋に演算させるとinteger型が返ってくる。たとえばこんな具合。*1

select
  case when term_end > some_day then term_end - term_start + '2 days'::interval
  else term_end - term_start end as hoge
from
  table

この場合、case文の条件によって返り値が変わってしまうためエラーが起きる。しかしここでextract関数を使ってやるとうまくいくことがある。たとえば上の例で最初の条件をinteger型にしたいときはwhen以下を

extract (days from ((term_end - term_start + '2 days')::interval))

としてあげたりとか。「直接castすればいいではないか」と思うかもしれないが、その場合たとえば問題の部分の戻り値が"5 days"だった場合、それをどの単位にすればよいのか判断できないため「interval型はinteger型に変換できない」旨のエラーが発生する。
詳しくは以下のページ参照。

*1:実際に試したコードとは違うので期待通りに動作するとは限りません