• ベストアンサー
  • すぐに回答を!

SQLのBetween句

SQL初心者です。 どなたかヒントでもよいのでご教授お願いします。 分からない箇所は以下の2つです。(SQLは下方に示しています) ・where句のbetweenの箇所にカラム指定箇所にTO_CHAR(SYSDATE -2, 'YYYYMMDD') を入れた時、何を評価しているのか? ・where句のbetweenの条件部分のカラム名に(+)をつけた場合何を意味しているのか? この2つがどうしても分かりません。 このSQLについて知識お持ちに方よろしくお願いします。 環境は次の通りです。 ------------------------ ■環境 ・OracleDatabase10.2 ■テーブル構成 テーブルは以下の2つです。 ・sample1 ・sample2 sample1テーブルに以下のカラムがあります。 ・test1 sample2テーブルに以下のカラムがあります。 ・test2 ------------------------ ■SQL SELECT * FROM sample1 s1, sample2 s2 WHERE TO_CHAR(SYSDATE -2, 'YYYYMMDD') BETWEEN s1.STAYMD(+) AND s2.(+)

共感・応援の気持ちを伝えよう!

  • 回答数1
  • 閲覧数4742
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • 回答No.1

質問の趣旨がつかみきれていなければごめんなさい。 書かれているクエリの末尾の「AND s2.(+)」というのはどう考えてもおかしいので、 ここが「AND s2.ENDYMD(+)」とでもなっている前提で書きますと、 (sample1にSTAYMDというカラムがあることも書かれていませんけど) ・TO_CHAR(SYSDATE-2, 'YYYYMMDD')が「今日から2日前のYYYYMMDD文字列」であると理解しているならば、  評価しているのは、例えば今日なら「20081222」という文字列です。 BETWEEN句も結局真であるかどうかを判断することに変わりはないわけですから、  FIELD1 BETWEEN 1 AND 10  という書き方でなくても構わないわけです。  7 BETWEEN FIELD1 AND 10  は、FIELD1が7以下であれば真になります。 ・書き換えたら理解しやすいと思います。 SELECT * FROM sample1 s1, sample2 s2 WHERE TO_CHAR(SYSDATE-2, 'YYYYMMDD') BETWEEN s1.STAYMD(+) AND s2.ENDYMD(+) => SELECT * FROM sample1 s1, sample2 s2 WHERE '20081222' BETWEEN s1.STAYMD(+) AND s2.ENDYMD(+) => SELECT * FROM sample1 s1, sample2 s2 WHERE '20081222' >=s1.STAYMD(+) AND '20081222'<=s2.ENDYMD(+) => SELECT * FROM sample1 s1, sample2 s2 WHERE s1.STAYMD(+)<='20081222' AND s2.ENDYMD(+)>='20081222' そうやってみると、外部結合を示す(+)がこの場合何の意味もないことが分かるでしょう。 (外部結合しようにも相手はテーブルではないからです) もともと外部結合というのは片側に対象データがなくても抽出することを目的として使うものですが、もしそういう意図で(+)を書いているのだとしても、片側がNULLだとBETWEENは常に真にはならないので、意味がありません。 SELECT * FROM sample1 s1, sample2 s2, (SELECT TO_CHAR(SYSDATE-2, 'YYYYMMDD') DT FROM DUAL) s3 WHERE s3.DT BETWEEN NVL(s1.STAYMD(+),'19000101') AND NVL(s2.ENDYMD(+),'20991231') と書くなら、少しは意味があるかもしれませんね。

共感・感謝の気持ちを伝えよう!

質問者からのお礼

こんなに詳しくありがとうございました、理解しました。 私の間違いまで指摘してもらい本当に助かりました。

関連するQ&A

  • betweenで境界値が取得できない。

    連番の歯抜け値を取得するSQLを作りたいと思っています。 例えば、カラムAに、1,2,3,5,6,7,9,10(4と8が抜けている) と数値の入っているテーブルAがあるとします。 これに対して、 SELECT MIN(カラムA + 1) FROM テーブルA WHERE (カラムA + 1) NOT IN (SELECT カラムA FROM テーブルA) とSQLを投げた場合、4が取得できます。 これにbetween句を付与したいのですが、そうすると境界値が なぜか取れなくて困ってます。 具体的には、 SELECT MIN(カラムA + 1) FROM テーブルA WHERE (カラムA + 1) NOT IN (SELECT カラムA FROM テーブルA) AND BETWEEN 8 AND 10 とした場合、NULLが返ってきてしまいます。 普通、BETWEENは境界値も対象になるはずですが、何故このような 結果になってしまうのでしょうか? 修正点をご教授いただけないでしょうか? 宜しくお願いします。

  • オラクルSQLについて

    初心者です。困っています。 テーブルC 日付_番号_ステータス 1/3____1_____Q 1/5____2_____R 1/6____5_____G 1/7____7_____P 1/20__ 9_____R 2/1___10_____R このようなテーブルを、1.日付順、2.番号順の優先順位で、選択していく為、下記のようなSQLを作成しました。 SELECT 番号 FROM テーブルC WHERE (TO_CHAR([日付],'yyyyMMdd') || [番号]) IN (select MIN((TO_CHAR([日付],'yyyyMMdd') || [番号])) FROM テーブルC WHERE (TO_CHAR([日付],'yyyyMMdd') || [番号]) > (SELECT (TO_CHAR([日付],'yyyyMMdd') || [番号]) FROM テーブルC WHERE [番号]=前回編集した番号)) ユニークなのは番号だけです。 これに、ステータス が RかPの場合 を加えたいだけなのですが、SQLが多くなりすぎて、困難になってしまいました・・・。 どなたかご教授頂ければ幸いです。

  • SQLのbetweenについて

    現在SQLを勉強しています。 C♯とSQLServerを使用しているのですが betweenを使って困った点があります。 自分で入力するAとB(どちらも数字)をbetweenの条件にしていしているのですが 例) select フィールド名 from テーブル where フィールド名 between A and B; → テーブルのフィールド名 の中のAからBのデータを選択する は問題ありません。 ですがAとBが未入力だとエラーが当然でてしまいます。 そこで未入力だとフィールド名の中を全件selectするようにしたいのですが、これはbetween で出来るのでしょうか? おそらくは条件であれこれ指定するのだと思いますが… 回答お願いします

  • 時間の抽出条件

    業務で開発中、どうしてもわからなかったので質問させていただきます。 あるテーブルから「データを抽出する日の14時までにできたデータのみを抽出する」というSQLですが、 データを抽出する日→SYSDATEでYYYYMMDDまでを取得する考えです。 このあとの14:00:00という条件をつけるSQLの書き方がわかりません。 このような書き方ではだめでしょうか? SELECT * FROM T_TEST WHERE DATAYMD < TO_CHAR(SYSDATE '14:00:00','YYYYMMDD HH24:MI:SS'); DATAYMDはCHAR型で8バイトで入っています。 よろしくお願いいたします。

  • Oracle SQL DELETE文のレスポンス

    いつもお世話になっております。 この度は、手前のSQL文において DELETE文のレスポンスが上がらずに難儀しています。 現在DELETE処理はバッチにて行っています。 最初にSELECTにて抽出を行ったものをバックアップにとり、 次は同様の条件でDELETE文で処理しています。 この際に、SELECTでは1秒程度で済んだ処理が、 DELETE文ではレスポンスが返ってこないという状況です。 何がまずいのか、どう工夫すればいいのか 色々変えてみましたがレスポンスは改善されません。 SQLと条件は以下です。 【SQL文】 SELECT 複数の項目 FROM TABLEA A WHERE NOT Exists(SELECT 'X' FROM TABLEB B WHERE A.ITEMNO = B.ITEMNO) AND NOT Exists(SELECT 'X' FROM TABLEC C WHERE A.ITEMNO = C.ITEMNO AND to_char(LAST_DAY(ADD_MONTHS(SYSDATE,-4)),'YYYYMMDD') < C.REPYMD) AND NOT Exists (SELECT 'X' FROM TABLEA2 A2 WHERE A.ITEMNO = A2.ITEMNO AND to_char(LAST_DAY(ADD_MONTHS(SYSDATE,-4)),'YYYYMMDD') < to_char(A2.CREATEDATE,'YYYYMMDD')) AND NOT Exists(SELECT 'X' FROM TABLEC C WHERE A.ITEMNO != C.ITEMNO AND to_char(LAST_DAY(ADD_MONTHS(SYSDATE,-4)),'YYYYMMDD') < to_char(A.CREATEDATE,'YYYYMMDD')) 上記のSELECT文の後に処理されるDELETE文は 「SELECT 複数の項目 FROM TABLEA A」 ⇒ DELETE FROM TABLEA A としたもので、 条件は全てSELECT文と同様のものを使用しています。 ◆条件を言葉で明記すると以下のようになります。 1.Bテーブルに存在するものは削除対象外とする 2.AテーブルのアイテムIDとCテーブルのアイテムIDは一致する。   AテーブルのCREATEDATEとCテーブルのREPYMDのいずれかが3ヶ月以内のアイテムは   削除対象外とする 3.AテーブルもしくはCテーブルにしか存在しない場合は、各日付が3ヶ月以内のアイテムは   削除対象外とする 以上のようになっています。 どなたかアドバイスをいただければ幸いです。 宜しくお願い致します。

  • SQL 副問い合わせ

    以下のaテーブルのcardidと、bテーブルのnoが同じで、 かつ、bテーブルのryodtmが前月のデータを抽出する以下のsqlを、 aテーブルのcardidが、bテーブルのnoと同じで、かつ、ryodtmが前月分、 または、cテーブルのchangcardと同じで、かつ、ryodtmが前月分のを抽出する場合、 どうすればいいでしょうか? select * from a where cardid in ( select distinct(no) from b where kdncresbt ='1' and ryodtm >= TO_CHAR(ADD_MONTHS(TRNC(SYSDATE,'MONTH'), -1),'YYYYMM' ) || '01' and ryodtm < TO_CHAR(SYSDATE,'YYYYMM') || '01' )

  • sample1のテーブル内容をsample2のテーブルの形に変更させる

    sample1のテーブル内容をsample2のテーブルの形に変更させる 簡単な方法はないでしょうか? マクロ・VBAなどお教え頂けませんでしょうか? よろしくお願いします。 sample1 http://www17.atpages.jp/fxmaster/sample1.htm sample2 http://www17.atpages.jp/fxmaster/sample2.htm

  • すっきりとしたSQL文にしたいのですが

    Oracle9iにてテーブルのデータを更新しようと思っています。 目的としてはAAAのカラムa1とBBBのカラムb1が同一なレコードである場合、 AAAのa2にBBBのb2を更新したいのですが、 <条件> AAA:テーブル1 BBB:テーブル2 a1:CHAR b1:CHAR a2:VERCHAR b2:VERCHAR すべて必須で桁数は10 UPDATE AAA SET AAA.a2 = ( SELECT BBB.b2 FROM BBB WHERE AAA.a1 = BBB.b1) WHERE AAA.a1 = ( SELECT BBB.b1 FROM BBB WHERE AAA.a1 = BBB.b1) ; いまはこんな無駄の多そうなSQLしか分かりません。 この他にも条件が2つ追加される予定なので もっとすっきり更新できる方法を教えていただけませんでしょうか? よろしくお願いします。

  • SQL、between の指定方法について

    こんにちは、SQLについての質問なのですが、 PHPで以下のように、テキストボックスを指定して、値を検索 するような作りにしています。 print "<table><tr align=center>"; print "<td align=left>◎日付検索<br>"; print "<input type=text name=s_hiduke></td>\n"; print "<td align=left>◎入力者<br>"; print "<input type=text name=s_name></td>\n"; $where = ''; if($s_hiduke != ""){ $where .= $where ? "and s_hiduke~'$s_hiduke' ":"where  s_hiduke~'$s_hiduke' "; } if($s_name != ""){ $where .= $where ? "and s_name~'$s_name' ":"where  s_name~'$s_name' "; } if (!$sql) { $sql = "select * from syuhou_table ".$where;} else {$sql = str_replace("\\","",$sql);} 今回日付の部分にテキストボックスをもう一つ追加し、「5/10~5/15」 のように期間指検索が定出来るようにする為以下のようにソースを 変更したのですが上手く動作しません… print "<input type=text name=s_hiduke>~<input type=text name=s_hiduke2>&nbsp;&nbsp;</td>\n"; $where = ''; if($s_hiduke != ""){ $where .= $where ? "and s_hiduke~'$s_hiduke',  s_hiduke2~'$s_hiduke' ": "where s_hiduke between    s_hiduke~'$s_hiduke' and s_hiduke2~'$s_hiduke' "; } 何処を直せば正常に動くのか、お分かりになる方がいらっしゃいま したら、アドバイス頂けませんでしょうか。 長々とした文章になってしまい申し訳ございませんが、よろしく お願いいたします。

  • SQL文について

    テーブルの結合について教えてください。 (DBはオラクルです) select * from table1,table2 where table1.カラム名=table2.カラム名; で、結合が出来ることは分かりました。 やりたいことはテーブルの結合と、ある期間のデータを持ってきたいのです。 select カラム名 from table1 where カラム名 between '20020213' and '20020218'; で期間を決めて引き出すやり方も分かっています。 一度に結合と期間を決めて引き出すやりかたってどうすればよいですか? それとも不可能ですか? 教えてください。