[pgsql-jp: 26297] Re: 記念日等の範囲検索

Takao Kato sirius @ jp.fujitsu.com
2002年 6月 6日 (木) 10:18:44 JST


 加藤@川崎です。

> 条件絞り込みで
> a月b日($s_day)〜c月d日($e_day)の該当者を検索をするとした場合
> select * from user where memorial_day <= '$e_day' and memorial_day
> >='$s_day'
> 
> むりやり年をつけたして検索もできそうなかんじもしたのですが、年をまたぐ指
> 定の場合(例えば12/20〜1/10までを検索)などどうすればいいのかと。


朝の頭の体操と言うことで、少し考えてみました。手段として、

(1)時期を「月」単位で切ってしまう
(2)条件判定時にmemorial_dayに年を加えてしまう
(3)memorial_dayに年情報を加える

の3つの方法が「ぱっ」と思いつきます。


(1)時期を「月」単位で切ってしまう
   これは「月」で一度振るいにかけてしまうことで、12/20〜1/10なんて面倒
   臭い判定を避ける方法です。これは当然思いついていると思います。

   これに条件をもう一つ加えて、月を跨ぐ場合には上記条件を二回にわけて
   しまう、、、例えば 12/20〜12/31と1/1〜1/10

   クエリをどこから喰わせるのかで $e_day と $s_day の値を算出する方法
   が変わって来ますが、仮に分離した結果判定範囲が

      $s_day〜$e1_day
      $s2_day〜$e_day

   としたら
   
   select * from user where
    memorial_day between $s_day and $e1_day or
    memorial_day between $s1_day and $e_day;

   で良いですよね。(overlapsでもOK)

(2)条件決定時にmemorial_dayに年を加えてしまう
   memorial_dayに今年と来年の「年」情報を条件判定時に加えてしまうもの
   です。ただ「年」情報をどう加えれば良いかは別の方にお願いするとして、 ^^;;
   年情報を加えたフィールドとして memorial_now memorial_next とでもし
   て($s_dayと$e_dayにも年情報が加わっている)

   select * from user where
     memorial_now between $s_day and $e_day or
     memorial_next between $s_day and $e_day;

   でいけると思います。(overlapsでもOK)


(3)memorial_dayに年情報を加える
   (2)とは memorial_dayの型を初めから date 型(timestamp)にしておくとこ
   ろが異なります。くわえて、cronなどで日に1度(例えば0時に)現在よりも
   古い日の年情報を更新してしまいます。こうすれば(1)や(2)のように小細
   工しなくても($s_day/$e_dayともにdateかtimestamp型なら)

   select * from user where
     memorial_day between $s_day and $e_day;

   で終わりですよね。

   注意点としては、「誕生日」は更新しても「生年月日」は更新してはいけ
   ない、、、そりゃそうですよね。誕生日は毎年やってきますが、生年月日
   は一生で一度ですから。このようにカラムの入力値に依存する関係を忘れ
   て無闇に更新するとDBの意味がなくなったりします。

   聡明な皆さんはともかく、僕なんかは忘れてやってしまいそうです ^^;

こんなところかなぁ? ちなみにクエリ生成をPHPやPerlでやるならゴリゴリで
きます。が、SQLだけでもっとシンプルかつ聡明な方法ありましたら教えてく
ださい。^^
----
加藤@川崎
お便りは kato @ lantc.cs.fujitsu.co.jp まで



pgsql-jp メーリングリストの案内