• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:特殊な?日付データ条件のSELECT文で困っています。回答御願いします。)

特殊な日付データ条件のSELECT文で困っています

このQ&Aのポイント
  • 初心者のSQL構文の質問です。SQLServer2005のデータベースには特殊な日付データ条件があります。
  • テーブルにはデータ履歴と有効日付の情報があり、最新のデータには有効日付にはNULLが入るようになっています。
  • 指定した日付に該当するデータを取得するSELECT文を作成したいのですが、具体的な方法がわかりません。詳しい方のご教授をお願いします。

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

  • ベストアンサー
  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.7

#6の方のご意見は尤もだと思いますが、「SQL ServerのカテゴリでSQL Server2005を使っている人の質問に対し、SQL Serverの標準構文で回答する」ことにはあまり問題を感じないです。 全く同じ質問が知恵袋にも出ていて、そちらにも一往復回答がついていますが、そこで止まっているところを見ると、たぶん解決したんだろうと思っています。 ただ、OKWaveは質問を締めなくても履歴が残るので、後で見る人に「IS NULLの動きが設定でコントロールできる」という誤解を与えないようにコメントを追加しただけ、というのが正直なところです。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (7)

回答No.8

#4です。 ああ。確かにここまで書いてて検証してないというのはあたまわるすぎですね<私 失礼しました。 多分「ひとつでも式にNullがあるとすべてNullになる」というのを以前聞いてて、無条件にそれを信じ込んでいたせいだと思います。

全文を見る
すると、全ての回答が全文表示されます。
  • nda23
  • ベストアンサー率54% (777/1415)
回答No.6

#2です。 こういうことはあまり言いたくないのですが、特定のDBエンジンに依存 する話とか、特別な環境設定を云々と言うのは本筋ではないような… SQLを考える時、どういう理論で結果を得るかを考えることが先では ないですか?その上で、なるべく一般的な書式を模索するべきで、 特定DBエンジンに依拠する書式は止むを得ない場合にのみ使用する 方がSQLの移植性も向上するし、勉強にもなるのではないでしょうか。

全文を見る
すると、全ての回答が全文表示されます。
  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.5

#1,#3です。 #4の方のコメントはもしかしたら、私のクエリが通らない可能性について書いていただいたのかもしれないと思いますが、ANSI_NULLSはIS NULL/IS NOT NULLの動きには影響をあたえません。 http://technet.microsoft.com/ja-jp/library/ms188048(SQL.90).aspx >スクリプトが意図どおりに動作するようにするには、ANSI_NULLS データベース オプションや SET ANSI_NULLS の設定とは無関係に、NULL 値を含む可能性のある比較で、IS NULL と IS NOT NULL を使用するようにしてください。 なお、UNKNOWN OR TRUEはTRUEです。 http://technet.microsoft.com/ja-jp/library/ms188361(SQL.90).aspx つまり「有効日付>=@date OR 有効日付 IS NULL」は有効日付がNULLの場合、常に成立します。 したがって、残念ながら質問者さんが自分の環境で試すに際して、正しく書き換えてくれなかったのだろうと推測します。

millialia
質問者

お礼

いろいろと回答いただきありがとうございます。貼っていただいたURLとても参考になりました。考え方も教えていただきありがとうございます。SQLもっと勉強します。

全文を見る
すると、全ての回答が全文表示されます。
回答No.4

まず、 「有効日付>=@date OR 有効日付 IS NULL」 は、有効日付がNullの場合条件が成立するかどうかはデータベースの設定によります。 NULL 比較検索条件 http://msdn.microsoft.com/ja-jp/library/ms191270.aspx によると、 >SET ANSI_NULLS を ON にすると、比較する式の 1 つ以上が NULL の場合、TRUE または FALSE ではなく、UNKNOWN が返されます。 >Transact-SQL は、NULL 値について比較した後に TRUE または FALSE を返す比較演算子の拡張機能をサポートしています。このオプションは、ANSI_NULLS を OFF にするとアクティブになります。 なので、SET ANSI_NULLS が ONなら、「有効日付>=@date OR 有効日付 IS NULL」は有効日付がNull (Null)>=@date OR (Null) IS NULL →(Unknown) or (true) →(Unknown) なので、条件は成立しません。 その場合、 Case when 有効日付 is Null then 1   when 有効日付>=@date then 1   else 0 end =1 の用に場合分けする必要があるようです。 あと、SelectするときにID指定が必須だというなら order by して、top 1を取得するのが簡単だとは思います。

millialia
質問者

お礼

回答いただきありがとうございます。 order by でtop 1という考え方は全く思いつきませんでした。 ありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。
  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.3

#1です。 どうやって試されたかわかりませんが、先のクエリは条件を満たしていますよ。NULLしかなくてもちゃんと取得できます。 (こういう質問は通常こちらでも確認して回答を書いていますから)

全文を見る
すると、全ての回答が全文表示されます。
  • nda23
  • ベストアンサー率54% (777/1415)
回答No.2

先ず、論理を決めて考えましょう。新しい課題の度に苦労しますよ。 (1)ID毎に有効日付の最大値(最新日)を求める。 (2)上記中、最大値が指定条件以上のものがあれば、これを抽出する。 (3)上記中、最大値が指定条件未満で、有効日付がNullのものを抽出する。 (4)上記、(2)と(3)の集合が求めるクエリである。 (2)のクエリ SELECT MAX(履歴) AS 履歴,MAX(有効日付) AS 有効日付 FROM テーブル GROUP BY ID HAVING MAX(有効日付)>=指定日 ★有効日付≠NULLの最新データが指定日以降であることが条件  有効日付=NULLのデータの有無には関係しない。 (3)のクエリ SELECT MAX(履歴) AS 履歴,NULL AS 有効日付 FROM テーブル GROUP BY ID HAVING MAX(有効日付)<指定日 AND SUM(CASE WHEN 有効日付 IS NULL THEN 1 ELSE 0 END)>0 ★有効日付≠NULLの最新データが指定日以前だが、有効日付=NULLの  データがあることが条件 UNION句で(2)と(3)を繋げる。尚、履歴はオートインクリメントの ように、日付が最新のものほど大きい(つまり、比例している)と 想定しています。 ★の所を見てもらうと分かりますが、有効日付=NULLのデータが無く、  しかも、最新日が指定日以前のデータは抽出されません。

全文を見る
すると、全ての回答が全文表示されます。
  • jamshid6
  • ベストアンサー率88% (591/669)
回答No.1

入力日付を@dateとすれば SELECT ID,履歴,有効日付 FROM テーブル t WHERE 履歴 IN (SELECT MIN(履歴) FROM テーブル WHERE ID=t.ID AND (有効日付>=@date OR 有効日付 IS NULL)) ORDER BY ID

millialia
質問者

お礼

回答ありがとうございます。 MIN(履歴) で最小の履歴しか取ってこれないようです。 100 | 1 | 2009/5/15(~2009/5/15まで有効) 100 | 2 | 2009/7/15(2009/5/16~2009/7/15まで有効) 100 | 3 | NULL(2009/7/16~まで有効) 履歴のない1レコードのみのデータとしては 履歴1 | NULL (全期間有効) が必ず入ります。 範囲は各データで、重複するしないことを前提として、 取得したいデータとしては、 上記の通りで、入力日付に対して、取得データは1レコードのみ。 where 有効日付>=@date OR 有効日付 IS NULL とした場合は、 有効日付が入っている場合は、 確かに取ってこれるのですが、 NULL(最新データ)のみのデータが取ってこれません。 どうかご教授御願いします。。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 日付の条件の書き方

    SQLserver2005を使い始めた初心者です. 現在,日付の条件で躓いています. 番号 日付  1 2008/10/29 2 2008/11/02 3 2008/11/01 4 2008/11/03 というようなデータベースがありまして, MAX(日付)が今日から3日前以前のデータを抽出するという, 条件を書きたいのですが何かアドバイスを頂けたら幸いです.      

  • SQLServer7.0で、SELECT文で列を抽出する ※Nullと0の条件について

    SQLServer7.0で、SELECT文で列を抽出する際なんですが、 列A 列B --------- 1  Null 2  Null 3  1 ↑のテーブルから、列Aの1、2だけを抽出するSELECT文を SELECT * FROM XXX WHERE 列B <> 1 と作成したのですが、うまく動作しません(汗) データが一件も取れないのです。(列B:tinyint型、Null許容) テーブル内のデータをNull→0にして、同SELECT文で抽出すればうまくいったのですが。。 Nullデータを、<>XX という条件で取得することはできないんですかねえ・・・。 それとも、テーブルの設定か、条件の記述方法がまずいんでしょうか。 どなたか、ご存知あればアドバイスをお願いします。

  • SELECT文で条件にあったテーブルからデータを取得するには?

    WinServer2003,WinXP,ORACLR10g使用しています。 SQL文の問合せ(SELECT)で、条件にあったテーブルを読みデータを取得するにはどのようなSQLの記述方法が良いでしょうか、お願いします。 3つのテーブルがあります。 Kdata,M_Fuku,M_Shokuhin KdataのデータのフィールドKkubunが 1の時はM_Fukuから,5の時はM_Shokuhinから品名のデータを取得したいです。 Kdata 1 コード 2 日付 3 区分 4 数量 5 単価 M_Fuku 1 コード 2 品名 M_Shokuhin 1 コード 2 品名 日付  区分 品名    数量 単価 金額 060710  1  ジャケット 1  5000  5000 060711  5  玉子    2   100   200 このようにしたいと思っています。 よろしくお願いします。

  • select文の結果から新しいテーブル作成の方法

    SQLは初心者で現在勉強をしています。 (SQLServer2000を使用) select文の結果から新しいテーブル作成したいのですが、下記SQLで上手くいきません。 どなたかアドバイス宜しくお願いします。 create table 新テーブル as select OrderID, Prd.ProductID, ProductName, Prd.UnitPrice from "Order Details" Ord inner join Products Prd on Ord.ProductID = Prd.ProductID (エラー内容) キーワード 'as' 付近に正しくない構文があります。 SQLserverでは 『create table 新テーブル as』の構文は使用できないのでしょうか?

  • 条件をつけて日付の古い行を抜き出したい

    SQLserver2005を使っています。 下記のようなテーブルがあります。 ID 処理番号  日付   Data AA  1    2008/1/1  10 AA  1    2008/1/2  11 AA  1    2008/1/3  12 AA  2    2008/1/4  13 AB  3    2008/1/5  14 AB  3    2008/1/6  15 AB  4    2008/1/7  16 この時に「IDと処理番号が一致した場合、日付の一番古い行を抜き出す」 という条件でデータの抽出をすることは可能でしょうか 結果は下記のようになります。 ID 処理番号  日付   Data AA  1    2008/1/1  10 AA  2    2008/1/4  13 AB  3    2008/1/5  14 AB  4    2008/1/7  16 下のような命令文を作ったのですが、 「Data列」が抜き出せません。 select ID,処理番号,min(日付) from テーブルA Group by ID,処理番号 一度上の命令文でテーブルを作って元のテーブルとマッチングさせるしかないのでしょうか?出来れば一発で抜き出したいです。 ご教授宜しくお願いします。

  • oracle 最新日付との比較

    いま、同一商品番号の最新日付を利用した条件が うまく作れず悩みながら色々試していますが、 うまくいきません。 やりたいことは、 1,AテーブルとBテーブルの 商品番号が同じ場合は除外します。 2,残されたデータから次はCテーブルの中にある 同一商品番号で、最新の日付が当月の場合はデータを残す。 つまり、前月以前のデータは除外となります。 1まではできています。 Select * from aテーブル where not exists (select 'X' from bテーブル where a.商品番号 = b.商品番号) この先上記sqlにつなげてmax関数くくった最新日付と システム日付を年月のみで比較する等試みましたが、 求めた結果になりません。 上記sqlでビューを作成してといったことは、 今回やらずに一つのsqlのみでできないかと 試行錯誤です。 よきアドバイスございましたら、 宜しくお願い致します。

  • ある条件のSELECT文の作成について

    以下のSQLの作成で悩んでいます。 【内容】 抽出元テーブルの中で、あるコードが同じデータは、 ある項目を全て同じ値にして取得したい。 (例) ■抽出元テーブル コード SEQ FLG  1    1   1  1    2    1    3    2    1   0  2    2  2    3  3    1   1 コードは同じ物が1つ又は複数あります。 コードが同じ物にはSEQで番号が連番されます。 FLGの項目がありますが、SEQ=1のデータしか設定されていません。 ■求めたい結果 コード SEQ FLG  1    1   1  1    2   1    1    3   1  2    1   0  2    2   0  2    3   0  3    1   1 全てのデータでFLGを求めて取得します。 取得の仕方はコードが同じでSEQ=1の値を取ります。 抽出元テーブルと結果のデータ件数は同じになります。 抽出元テーブルと結果の違いは、FLGに値が埋まっているかどうかの違いのみです。 このテーブルのFLGはUPDATEする事は出来ません。 別表なども利用しないで、 selectのSQL文だけで対応したいです。 どのような方法で対応できるでしょうか? オラクルのバージョンは10gです。 よろしくお願い致します。

  • SELECT文での抽出条件

    以下のような処理を行いたいと思いますが SQL文の作成方法を御教授下さい。 【時間DB】 YEARMONDAY,HOUR,FLG, DATA ----------------------------- 20050528     1  1 10 20050528     2  1 20 20050528     3  1 30 20050528     4  1 40 . . . 20050528    22  1 40 20050528    23  1 50 20050528    24  1 60 【日DB】 YEARMONDAY,FLG, DATA ----------------------------- 20050528     1  250 処理内容:指定された日付で日DBの作成を行う。 抽出条件:フラグが全て等しい場合はその値を取得       :フラグが一致しない場合は0を取得 上記の場合,SQL文で抽出可能でしょうか? 以上,よろしくお願い致します。

  • ハガキ交換データのSQL文

    下記のような葉書のデータベースでのSQL分についてお尋ねします。 Parsonals データベースに、 年賀状と暑中見舞いとのデータテーブル(Cards)のほか、 個人データテーブル(Individuals)と 家族データテーブル(Family)と 住所データテーブル(Address)との4つのテーブルがあります。 4つのテーブルは、次のように構成されています。 Individuals, Family, Address, Cards です。 1.Individuals テーブルは、 ID (オートナンバー), Name (文字列), FamilyID (数値), AddID (数値) の4つのフィールド 2.Family テーブルは、 FamilyID (オートナンバー), FamilyName(文字列) の2つのフィールド 3.Address テーブルは、 AddID (オートナンバー), Address(文字列), Telephone(文字列) の3つのフィールド 4.Cards テーブルは、 CardID(オートナンバー), KindOfCard(YesNo), SendYear(数値 ヌル値許可), ReceiveYear(数値 ヌル値許可), IndividualID (数値) の5つのフィールド です。 個人データすべてのほか、個人ごとの家族データすべて、個人ごとの住所データすべて、 そして、個人ごとのKindOfCard(年賀状か暑中見舞いか)ごとにSendYearデータのうち最新のものと ReceiveYearデータのうちの最新のものを取得するSQL文を取得したいのです。 簡単にいえば、 個人個人に対して、その個々人の個人データ・家族データ・住所データのほか、 年賀状を送った最新の年と受けた最新の年、 暑中見舞いを送った最新の年と受けた最新の年を取得したいのです。 さらに、最新の送った年と最新の受けた年とが同一のときは、データが重複しますので一つに絞りたいです。 Cardsテーブルのフィールドには、SendYearもReceiveYearもありますので、単純にSendYearとReceiveYearを切り分けると当然データが重複するので、この重複は避けたいです。 このように毎年の葉書のやり取りを記録したデータから必要なデータを取り出したいというものです。私にとっては来年の年賀状を送るにあたって、どの人に出すべきかを判断する材料として、ぜひ取りだしたいビューなです。 かなり複雑なSQL文になるのかもしれませんが、どんなSQL文かを教えてください。 ぜひ、よろしくお願いします。

  • select文のサマリー

     select sum(A.列名1)  --列名1の型はnumber  from テーブル名 A where A.列名2 = 定数  and A.列名3 <> 定数; と言った簡単なSQLなのですが、 結果としてnull値が返ることはあるでしょうか? count では必ず数値が返ると思うのですが・・・sumの場合もヒットする値が1件もなかった場合0が返るのでしょうか?  また、sum()またはcnt()でnullが返されるような条件があるとしたらどんな時でしょうか?