- 締切済み
SQLでのデータ検索方法
以下のようにデータが格納されている テーブルAがすでにあります。 id in_time out_time 1 11:10 1 10:30 1 10:15 3 09:50 1 09:30 1 09:00 1 08:30 2 08:10 1 07:50 2 07:40 1 07:30 ここでin_timeとout_timeの範囲が指定されたとき 範囲内でidごとにin_timeとout_timeがセットにな っているデータのみ抽出したいのです。 例えば in_time:7:00~10:20 out_time:8:00~11:30 と指定されたとき、検索結果を id in_time out_time 1 10:15 1 09:30 1 09:00 1 08:30 2 08:10 2 07:40 と表示したいのです。 プログラムで1レコードずつ処理するしかない と思っているのですが、SQLで上記のような結果 を取得する方法はあるのでしょうか。 環境は、 RHEL 5 postgesql 8.1.9 です。
- みんなの回答 (4)
- 専門家の回答
みんなの回答
- nda23
- ベストアンサー率54% (777/1415)
【考え方】 in_timeから見て、idが等しく、out_timeがin_timeより大きいものの うち、最小のものがペアとなるout_time SELECT A.id,A.in_time,MIN(B.out_time) outtm FROM (SELECT id,in_time FROM テーブルA WHERE to_char(in_time,'HH24:MI') BETWEEN '07:00' AND '10:20') A LEFT JOIN (SELECT id,out_time FROM テーブルA WHERE to_char(in_time,'HH24:MI') BETWEEN '08:00' AND '11:30') B ON A.id=B.id AND A.in_time<B.out_time GROUP BY A.id,A.in_time 但し、上記を実行すると、下記のように出力される。 id in_time out_time 1 08:30 09:00 1 09:30 10:15 2 07:40 08:10
- o123459876
- ベストアンサー率59% (19/32)
postgresqlの動作環境無いのでoracleで実行しました in_time,out_timeが文字列なら ----------------------------------------------------------- select id,in_time,out_time from( select id,in_time,out_time, (select min(b.out_time) from te b where b.ID = a.ID and coalesce(replace(a.in_TIME,':',''),'0') < coalesce(replace(b.out_TIME,':',''),'0') ) xxx, (select max(b.in_time) from te b where b.ID = a.ID and coalesce(replace(a.out_TIME,':',''),'0') > coalesce(replace(b.in_TIME,':',''),'0') ) yyy from te a ) where (coalesce(replace(in_TIME,':',''),'0') between replace('07:00',':','') and replace('10:20',':','') and coalesce(replace(xxx,':',''),'0') between replace('08:00',':','') and replace('11:30',':','') ) or (coalesce(replace(out_TIME,':',''),'0') between replace('08:00',':','') and replace('11:30',':','') and coalesce(replace(yyy,':',''),'0') between replace('07:00',':','') and replace('10:20',':','') "ID","IN_TIME","OUT_TIME" "1","","10:15" "1","09:30","" "1","","09:00" "1","08:30","" "2","","08:10" "2","07:40","" ----------------------------------------------------------- in_time,out_timeがdata型なら select id,in_time,out_time from( select id,in_time,out_time, (select min(coalesce(replace(to_char(b.out_time,'hh:mi'),':',''),'0') ) from te2 b where b.ID = a.ID and coalesce(replace(to_char(a.in_TIME,'hh:mi'),':',''),'0') < coalesce(replace(to_char(b.out_TIME,'hh:mi'),':',''),'0') ) xxx, (select max(coalesce(replace(to_char(b.in_time,'hh:mi'),':',''),'0') ) from te2 b where b.ID = a.ID and coalesce(replace(to_char(a.out_TIME,'hh:mi'),':',''),'0') > coalesce(replace(to_char(b.in_TIME,'hh:mi'),':',''),'0') ) yyy from te2 a ) where (coalesce(replace(coalesce(replace(to_char(in_TIME,'hh:mi'),':',''),'0'),':',''),'0') between replace('07:00',':','') and replace('10:20',':','') and coalesce(replace(xxx,':',''),'0') between replace('08:00',':','') and replace('11:30',':','') ) or (coalesce(replace(coalesce(replace(to_char(out_TIME,'hh:mi'),':',''),'0'),':',''),'0') between replace('08:00',':','') and replace('11:30',':','') and coalesce(replace(yyy,':',''),'0') between replace('07:00',':','') and replace('10:20',':','') ) "ID","IN_TIME","OUT_TIME" "1","","2009-08-01 10:15:00" "1","2009-08-01 09:30:00","" "1","","2009-08-01 09:00:00" "1","2009-08-01 08:30:00","" "2","","2009-08-01 08:10:00" "2","2009-08-01 07:40:00","" -----------------------------------------------------------
- めとろいと(@naktak)
- ベストアンサー率36% (785/2139)
結構汚くなっちゃいましたけど、一応できました。 全角スペース入れてるので置換して下さい。 Oracle上で試したので微妙に文法誤ってるかもしれません。 8.1.9ならいけそうなことしかしてないので、微妙な文法違いは直して下さいね。 SELECT id, in_time, out_time FROM test A WHERE A.in_time >= to_date('1899/12/30 7:00', 'yyyy/mm/dd hh24:mi:ss') AND A.in_time <= to_date('1899/12/30 10:20', 'yyyy/mm/dd hh24:mi:ss') AND EXISTS(SELECT 1 FROM test B WHERE B.id = A.id AND B.out_time >= TO_DATE('1899/12/30 8:00', 'yyyy/mm/dd hh24:mi:ss') AND B.out_time <= TO_DATE('1899/12/30 11:30', 'yyyy/mm/dd hh24:mi:ss') AND B.out_time = (SELECT MIN(C.out_time) FROM test C WHERE C.id = A.id AND C.out_time >= A.in_time) ) UNION ALL SELECT id, in_time, out_time FROM test A WHERE A.out_time >= TO_DATE('1899/12/30 8:00', 'yyyy/mm/dd hh24:mi:ss') AND A.out_time <= TO_DATE('1899/12/30 11:30', 'yyyy/mm/dd hh24:mi:ss') AND EXISTS(SELECT 1 FROM test B WHERE B.id = A.id AND B.in_time >= TO_DATE('1899/12/30 7:00', 'yyyy/mm/dd hh24:mi:ss') AND B.in_time <= TO_DATE('1899/12/30 10:20', 'yyyy/mm/dd hh24:mi:ss') AND B.in_time = (SELECT MAX(C.in_time) FROM test C WHERE C.id = A.id AND C.in_time <= A.out_time) ) これだとin_timeとout_timeがグループされて出てきますが、 in_time、out_timeがセットで交互に出てこないとダメでしょうか?
- めとろいと(@naktak)
- ベストアンサー率36% (785/2139)
> idごとにin_timeとout_timeがセット 何をもってそう判断すれば良いのでしょうか? このレコードからすると、 1 11:10 1 09:30 がセットである可能性もあると思うのですが。
補足
説明不足でした、すみません。 in_timeのレコードから現在に向かって探し、 最初に見つかった同じidでout_timeが入力さ れているレコードがセットになります。