質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JSP

JSP(Java Server Pages)とは、ウェブアプリケーションの表示レイヤーに使われるサーバーサイドの技術のことです。

MVC

MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

3回答

4439閲覧

オラクル SQL 予約日重複チェックについて

noririn

総合スコア37

JSP

JSP(Java Server Pages)とは、ウェブアプリケーションの表示レイヤーに使われるサーバーサイドの技術のことです。

MVC

MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

2グッド

0クリップ

投稿2016/08/13 08:57

編集2016/12/05 02:57

現在ある予約管理システムを作成しております(MVCモデル)

選択された予約from年月日〜予約to年月日を、
バインド変数を使用し、DBに登録されているデータと重複していないかチェックしたいと思っております。

SQLのtableは

SQL

1 2CREATE TABLE RESERVE( 3STARTDAY DATE, 4ENDDAY DATE, 5ROOMCODE CHAR(2), 6PEOPLE NUMBER(2), 7BASS CHAR(1), 8REPRESENTATIVE VARCHAR(20), 9ID CHAR(9), 10PRIMARY KEY(ID), 11); 12

上記のように作成しております。

こちらを元に、jspファイルから入力された日付の重複チェックをdaoクラスで行います。
重複していたらCOUNTが1以上を返すようにしたいのですが、
重複していても0を返してしまいます。

作成したSQL文は下記です

SQL

1 2String SELECT_COUNT_QUERY = " 3 4SELECT COUNT(*) AS COUNT FROM RESERVE 5WHERE ROOMCODE=?(ID) 6AND ((STARTDAY <= ?(from年月日) 7AND ?(from年月日) < ENDDAY) 8AND (STARTDAY < ?(to年月日) 9AND ?(to年月日) <= ENDDAY)) 10 11"; 12

daoクラスで作成した重複チェックソースは下記です

java

1public boolean isCheckOverlap(Connection con,String fromYMD,String toYMD,String roomCode) throws SQLException{ 2 3 //roomCodeにはID,fromYMD,toYMDにはyyyy/mm/dd形式の年月日が入っています 4 5 //重複チェック変数 6 Integer overlap = null; 7 8 //判定変数 9 boolean flag = true; 10 11try{ 12 13 //重複チェックSQL文をプリコンパイル 14 PreparedStatement ps = con.preparedStatement(SELECT_COUNT_QUERY); 15 16 //バインド変数に値をセット 17 ps.setString(1,roomCode); 18 ps.setString(2,fromYMD); 19 ps.setString(3,fromYMD); 20 ps.setString(4,toYMD); 21 ps.setString(5,toYMD); 22 23 //セレクトの結果を受け取る 24 ResultSet rs = ps.executeQuery(); 25 26 //最初の行を呼び出す 27 rs.next(); 28 29 //COUNTを取得 30 overlap = rs.getInt("COUNT"); 31 32 //COUNTの結果が1以上ならfalseを返す 33 if(overlap >= 1){ 34 35 flag = false; 36 } 37 38}catch(SQLException e){ 39 throw e; 40}finally{ 41 try{ 42 if(rs != null)rs.close(); 43 if(ps != null)ps.close(); 44 }catch(SQLException e){ 45 e.printStackTrace(); 46 } 47} 48return flag; 49} 50

上記で作成しましたが、重複したデータでもtrueになります。

SQL*PLUSに直接from年月日に'2016/08/11'、to年月日に'2016/08/14'と日付を入力するとちゃんとCOUNT数を返してくるため、

SQL

1 2SELECT COUNT(*) AS COUNT FROM RESERVE 3WHERE ROOMCODE=? 4AND ((STARTDAY <= TO_DATE(?,'yyyy/mm/dd') 5AND TO_DATE(?,'yyyy/mm/dd') < ENDDAY) 6AND (STARTDAY < TO_DATE(?,'yyyy/mm/dd') 7AND TO_DATE(?,'yyyy/mm/dd') <= ENDDAY)); 8

等修正してみましたが、やはり重複していてもtrueを返してしまいます・・

SQL文から間違っていますでしょうか?

大変お手数ですが、アドバイス頂けると幸いです。

どうぞよろしくお願い致します。

garasya, ikuwow👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

OracleSQLパズル 10-226 OverLaps述語
https://oraclesqlpuzzle.ninja-web.net/10-226.html
を見ながら作ってみました :-)

sql

1select count(*) 2 from RESERVE 3 where STARTDAY <= toYMD 4 and fromYMD <= ENDDAY; 5

この不等式は、ゲームプログラミンングでの
長方形同士の当たり判定でも使われるものです。

ブール代数を使って、下記のように同値変形すれば一致します。

sql

1 (fromYMD BETWEEN STARTDAY AND ENDDAY) 2OR (toYMD BETWEEN STARTDAY AND ENDDAY) 3OR (STARTDAY > fromYMD AND ENDDAY < toYMD) 4 5 (STARTDAY <= fromYMD and fromYMD <= ENDDAY) 6OR (STARTDAY <= toYMD AND toYMD <= ENDDAY) 7OR (fromYMD < STARTDAY AND ENDDAY < toYMD) 8 9A STARTDAY <= fromYMD 10B fromYMD <= ENDDAY 11C STARTDAY <= toYMD 12D toYMD <= ENDDAY 13E fromYMD < STARTDAY 14F ENDDAY < toYMD 15として 16 17AならばC 18DならばB 19EならばB 20FならばC 21Aの否定がE 22Dの否定がF 23を使って 24 25 A*B + C*D + E*F 26=A*B*C + B*C*D + B*E*C*F 27=B*C*(A+D+E*F) 28=B*C*(A+D+Not(A)*Not(D)) 29=B*C*(A+D+Not(A+D)) 30=B*C 31

投稿2016/08/15 10:45

編集2019/03/12 06:35
AketiJyuuzou

総合スコア1147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

noririn

2016/08/15 13:39

AketiJyuuzou様 ご回答ありがとうございます! またコードまでご丁寧に書いてくださりありがとうございます。 すみません、少し理解をするのに時間がかかっていまして・・^^; じっくり拝見しながら考えたいと思います・・・! 本当にありがとうございます^O^
guest

0

ベストアンサー

質問者さんのおっしゃる重複の定義が、
予約したい期間内に別途予約された日付期間が含まれている状態を指すのでしたら、
以下の考え方でいけるかと思われます。

別解もあるのですが、
期間・範囲の重複を判断する場合の一番単純な考え方は以下の3条件のいずれかを満たすことを確認します。

  1. 登録したいデータの開始点を含むデータが他に登録されている場合は重複
  2. 登録したいデータの終了点を含むデータが他に登録されている場合は重複
  3. 登録したいデータの開始点と終了点が他に登録されているデータの開始・終了点を含む場合は重複

これをSQLで正直に表すと下記イメージになります。

SQL

1(fromYMD BETWEEN STARTDAY AND ENDDAY) -- 開始日含む 2OR (toYMD BETWEEN STARTDAY AND ENDDAY) -- 終了日含む 3OR (STARTDAY > fromYMD AND ENDDAY < toYMD) -- 別データの開始・終了日を含む

ちなみにこの条件により取得されたデータ件数が1以上は、
重複ありとなります。(isCheckOverlapではfalseを返すことになります)

###追記
SQLPlusで想定通り動作するけど、
PHPで想定通りとならないケースというのは、

  1. バインドパラメタ(?に設定する値)が想定と異なる値を設定している
  2. SQLの記述方法に差異がある

上記のどちらかとなるので、その観点でプログラムを確認してみて下さい。

1つ目の着眼点はsetStringなどで値を設定している箇所で、
デバッグ機能を利用し想定した値が変数に設定されているかの確認しましょう。

2つ目の着眼点はJava上でのSQLの記載と、
SQLPlusで実行したSQLの差分を比較してみましょう。
パラメタを「?」としている箇所以外で大きな差分があれば、
そこが実行結果が異なる要因となっている箇所と推測できます。

また重複条件の判定について文面だけだとわかり辛いので、
追加でアドバイスをば。

こちらは質問者さんなりに重複条件を考えていらっしゃると思いますが、
どうしてもプログラミングのみ(頭内で考えるだけ)でわからない場合は、
一度EXCELや紙などにどういったケースが重複となるかを書き出すと整理しやすいです。

例えば以下のように書き出すと、
どのように条件を付ける必要があるか見えてきませんか。

A.今回登録予定の予約 A'.登録済の予約 ①A1(開始日)はA'1とA'2に含まれる A |----------| A1 A2 A'|-----| A'1 A'2 ②A2(終了日)はA'1とA'2に含まれる A |----------| A1 A2 A'|-----| A'1 A'2 ③A1、A2はA'1、A'2を含んでいる A |---------------| A1 A2 A'|-----| A'1 A'2

投稿2016/08/13 11:41

編集2016/08/13 23:17
Panzer_vor

総合スコア1636

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

noririn

2016/08/14 05:52

KotoriMaturi様 ご回答頂きましてありがとうございます。 御礼が遅くなり申し訳ありません。 またこんなにご丁寧にありがとうございます。 再度確認してみます! 取り急ぎ御礼まで・・ 本当にありがとうございました。
guest

0

sql

1? BETWEEN A AND B 2OR 3? BETWEEN C AND D

かな?

投稿2016/08/13 09:19

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/08/13 09:21

同様の意味をそのクエリに当てはめるなら3つ目のandをorに
noririn

2016/08/14 05:53

haruka-kanata様 ご回答ありがとうございます。 勉強になります・・ 再度確認してみます。 本当にありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問