• 締切済み

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 です。

みんなの回答

  • nda23
  • ベストアンサー率54% (777/1415)
回答No.4

【考え方】 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

回答No.3

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","" -----------------------------------------------------------

回答No.2

結構汚くなっちゃいましたけど、一応できました。 全角スペース入れてるので置換して下さい。 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がセットで交互に出てこないとダメでしょうか?

回答No.1

> idごとにin_timeとout_timeがセット 何をもってそう判断すれば良いのでしょうか? このレコードからすると、  1         11:10  1   09:30 がセットである可能性もあると思うのですが。

mlc56724
質問者

補足

説明不足でした、すみません。 in_timeのレコードから現在に向かって探し、 最初に見つかった同じidでout_timeが入力さ れているレコードがセットになります。

関連するQ&A

  • SQLの書き方について

    (1)の様なテーブルから結果を(2)の様にしたいのですが どのようなSQLを書いたら表示できるのかわかりません。 アドバイスなどをお願い致します。 (新たにView等を作成するなどでもかまいません。) (1)dept_id / item_id / day / time (カラム) 1111 / 0001 / 20090101 / 60 (レコード1) 1111 / 0001 / 20090102 / 30 (レコード2) 1111 / 0002 / 20090101 / 40 (レコード3) 1112 / 0001 / 20090101 / 30 (レコード4) (2)dept_id / item_id / time1 / time2 1111 / 0001 / 60 / 30 1111 / 0002 / 40 / 1112 / 0001 / 30 /

  • 1つのSQLで2段階の抽出を行いたい

    恐らくそれほど複雑なSQLではないと思いますが、中々SQLが作成できず困っています。 回答いただければ嬉しいです。 以下のテーブルがあったと仮定します。 テーブル名:  売上げ明細 カラム:  ・商品ID … 売上げ明細なので一意ではありません  ・単価 … 同じ商品IDでも、レコードによって単価は異なります  ・数量 … 1~5の整数のみとします 実際のデータは以下の通りです。 商品ID,単価,数量 1001,50,2 1001,60,5 1002,90,3 1003,60,5 1003,80,4 1003,90,1 1004,60,3 上記データを以下の通り抽出するには、どのようなSQLを組めばいいでしょうか? 1.まず各商品IDの中から単価が最大のレコードだけを取り出す 商品ID,単価,数量 1001,60,5 1002,90,3 1003,90,1 1004,60,3 2.次に数量でgroup by して、件数をカウントする 数量,件数 1,1 3,2 5,1 1つのSQL文で2の結果が得られれば、途中の抽出条件は特に問いません。 ちなみにMySQL5を使っています。 よろしくお願いします。

    • ベストアンサー
    • MySQL
  • フラグがたっているデータがあったら検索かけたい・・。

    Aテーブルにグループ番号、ID番号、氏名、ステータスフラグが格納されており、BテーブルにID番号、氏名、電話番号、住所が格納されているとします。検索したい条件は、同じグループの中で、ステータスフラグがたっているレコードが1件でもあれば、ID番号を使って、Bテーブルと結合してグループ番号でGROUP BYしてデータがとりたいのです。例えば、Aテーブルにグループ番号001のグループ番号を持つレコードが5レコードあり、そのうちステータスフラグがたっているレコードが1レコード。002のグループ番号を持つレコードが3レコードあり。ステータスフラグがたってるのが0レコードだとします。結果として、001のグループはステータスフラグがたっているレコードがあるから、検索対象になるが、002はステータスフラグがたっているレコードがないので、検索対象にならないといった具合なんですが・・・。よろしくお願いします。自分で考えたSQLは次のものです。SELECT * FROM A, B WHERE A.ID_NUMBER=B.ID_NUMBER GROUP BY A.GROUP_NUMBER HAVING COUNT(A.STATUS=1)>0 こんな感じです。ただCOUNT関数ではこれではダメみたいで・・・。まだ、1年目の新人なので、どなたかご教授お願いします。

  • データがあれば○○なければのSQL

    基本的なことなのかもしれませんが・・・ AとBというテーブルがあり、あるタイミングでAを元にBを作成します。つまりBはデータがある場合とない場合があります。また、2つは関連番号で紐づいています。 Aテーブルを抽出したい時に、抽出条件は以下です。 ・Bテーブルのステータスが1であれば抽出 ・Bテーブルのステータスが0であれば非抽出 ・Bテーブルにデータがなければ抽出 INNER JOINだとデータがない時に抽出できないし、 WHERE句にCASE句を入れればいいのかなと思いましたが、テーブルにデータがあればなんて条件書けないしで詰まりました。 SELECTした結果に対して条件つけて抽出する手も思いつきましたが もっと美しいSQLがあれば教えてもらえないでしょうか。 環境はSQLServerです。よろしくお願いします。

  • SQLでのデータチェック方法

    いつもお世話になっております。 SQLでのデータチェック方法について教えてください。 【売上テーブル】 日付、商品、代理店、金額 ---------------------- 5/1 消しゴム AA商店 100 5/1 鉛筆    BB商店 200 5/2 鉛筆    ZZ商店 200 5/2 万年筆  CC商店 150 【商品マスタテーブル】 品名 ----------- 消しゴム 鉛筆 【代理店マスタテーブル】 代理店 ----------- AA商店 BB商店 CC商店 この中で各種マスタに存在しないデータを抽出したいです。 select * from 売上テーブル where 商品 not in (select 品名 from 商品マスタ) or 代理店 not in (select 代理店 from 代理店マスタ) で抽出できるのはわかるのですが、 抽出結果に何故そのレコードが抽出されたのかをわかるようにしたいです。 日付、商品、代理店、金額  理由 ------------------------------- 5/2 鉛筆    ZZ商店 200 代理店マスタに存在しない 5/2 万年筆  CC商店 150 商品マスタに存在しない このような感じで理由も追加することは可能でしょうか? わがままですみません。 よろしくお願いします。

  • SQLの相談

    SQLの相談です。 以下のようなテーブルについて CREATE TABLE `record`( `id` INT, `timestamp` TIMESTAMP, `point` INT ); 1) id毎に最新5件のデータを抽出 2) 合計pointが420以上のidだけを抽出 したいのですが…。 1)の処理について、うまい解決策を思いつきません。 助言をお願いします。

  • 検索対象のデータが「複数レコード」を「1レコード」として獲得するSQL

    教えて下さい。 SQLの理解が乏しく、難航しています。 検索対象のデータが複数レコード存在するのですが、 それぞれのレコードの特定の項目を区切り文字で区切 ったデータとして1レコードとして獲得するSQLがあ ればと思いました。 イメージ) テーブルA ID shapeID name 1 1 交通安全 1 2 防火管理 2 1 什器 3 1 セキュリティー 区切り文字","とし、IDを1で検索した表示結果 交通安全,防火管理 教えてgooで調べてみると、「縦方向のデータを横方向 にするのは、SQLは苦手」とありました。 やはり無理なのでしょうか? 宜しくお願いします。

  • SQL文がわかんないっす…

    レコードを抽出するためのSQL文を教えてください。 テーブルは下記の通りです。 goodsID, stockNum, reservNum, date 1, 5, 4, 2008-11-4 2, 5, 3, 2008-11-4 2, 5, 2, 2008-11-5 :以下続く : で、2008年11月4日と、2008年11月5日の、(stockNum - reservNum) が両方とも2以上のgoodsID、つまり2を取得したいのです。 また、もし3以上と指定した場合は取得結果を空にしたいです(3つ目のレコードだけが取れると困ります)。 日付の範囲は可変です。 よろしくお願いします。

    • ベストアンサー
    • MySQL
  • SQLで、指定日条件のSQL文

    MySQLを使っています。 商品テーブルの中で、 同じ商品のレコードが複数あります。 その多数のレコード中に、日付項目があります。 そこから、 1)商品IDで重複せずに、2)指定日に、3)一番近い過去の日、4)指定日を含めて、複数ある未来の全レコード、を抽出するには、 どのようなSQL文を書けばよいでしょうか? 商品でユニークになるように、 1.過去に複数ある日付の中から、指定日に、一番近いレコード。 2.未来に複数ある日付の中の、全ての未来の、レコード。 3.同一商品レコードは、複数抽出されない。

  • sql 個別に情報取得方法

    こんにちは、 A,Bテーブルがあり、Aテーブル.ID = Bテーブル.IDの状態で IDごとの最新の更新時間を一件づつ取得したいのですが SQLで抽出することは可能でしょうか? 取得したい例------------------ ID、TIME(タイムスタンプ) 1、1356200000 2、1356228139 Aテーブル---------- ID 1 2 Bテーブル---------- ID、TIME(タイムスタンプ) 1、1350000000 1、1356200000 1、1300000000 2、1356228139 2、1356000000

    • ベストアンサー
    • MySQL