- ベストアンサー
クエリー抽出条件の最適化方法
- クエリー抽出条件の最適化方法を教えてください。
- 「作表条件」フォームの「日付1」、「日付2」を設定して、元のテーブルの「日付」項目から該当するデータを抽出するクエリーの条件式を作成しています。ただし、元のテーブルの日付がNULL値の場合に対応する方法を教えてください。
- 元のテーブルの日付がNULL値の場合でも抽出できるようにするためには、どのような条件式を記述すればよいでしょうか?
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
No.5です。 > 少なくとも一方が空白以外なら指定範囲のものを抽出 > 双方が空白なら『日付』がNullを含むすべてのものを抽出 了解しました。 とりあえず、フォームのヘッダ(またはフッタ)に『日付1』『日付2』の テキストボックス、及び、抽出を実行させるための『実行』コマンド ボタンが設置されている場合は以下のようになります。 '『実行』コマンドボタンのクリック時イベント Private Sub 実行_Click() On Error Goto エラー処理 '日付1・日付2の評価結果などを記録するための変数を用意 Dim sDate1 As String, sDate2 As String, sRS As String 'レコードソースに使用するテーブル/クエリの名前を定数として用意 Const conTableName As String = "テーブル1" Const conQueryName As String = "クエリ1" '日付1・日付2の入力状況を確認 '(後で使用するLen関数は、引数がNullだと演算結果も0では ' なくNullになってしまうため、Nullを予め空文字に変換) sDate1 = Nz(Me!日付1, "") sDate2 = Nz(Me!日付2, "") '入力状況で場合分け Select Case True Case Len(sDate1), Len(sDate2) '少なくとも一方が空白以外 '(Len関数の結果が0以外なら、Trueとみなされます) sRS = conQueryName Case Else '双方が空白の場合 sRS = conTableName End Select 'レコードソースを切替 Me.RecordSource = sRS 終了処理: Exit Sub エラー処理: 'エラー発生時は、エラー内容を表示の上、処理を中止 MsgBox Err.Number & ":" & Err.Description, , Me.Name & " 実行" Resume 終了処理 End Sub ・・・以上です。 なお、変数や定数を設置せず、いっぺんに処理を行ってしまうなら、 以下のようにも書けます(更にエラー処理も省略)。 『日付1』の値などを繰り返し使う場合(→例えばクエリを用意する 代わりに、VBAでレコードソースに直接SQL文を適用する、等)は 上記のようにした方が効率的ですが、今回はこちらでもOkかと・・・ ※こちらではLen関数を使用せず、「&」での結果が「""」(空文字) かどうかで判定しているため、テーブル/クエリの出てくる順序が 逆になっているので注意してください(汗) Private Sub 実行_Click() If (Me!日付1 & Me!日付2 & "") = "" Then '双方が空白 '※最後の「 & ""」がないと、「""」ではなくNullになり、 ' 正しく判断されなくなるので注意 Me.RecordSource = "テーブル1" Else '少なくとも一方が空白以外 Me.RecordSource = "クエリ1" End Select End Sub
その他の回答 (6)
- layy
- ベストアンサー率23% (292/1222)
片方に値がないかもしれない、ことより、必ず2つの日付に値があるとき検索、と考える方がはっきりします。 自=値あり、至=値あり 自=値あり、至=値なし 自=値なし、至=値あり 自=値なし、至=値なし 片方に値なし、はある方の値代入でよい。 2~4は問題なく検索 2~は2~2と同意、 ~4は4~4と同意、 双方無しは警告。 至は自があってこその値入力とすべき。 今回は、入力チェックでの対応と思います。
- DexMachina
- ベストアンサー率73% (1287/1744)
>「日付1」および「日付2」が空欄だとNULL値のレコードが > 抽出されません。 ご希望の動作は、テキストボックスが 少なくとも一方が空白以外なら指定範囲のものを抽出 双方が空白なら『日付』がNullのものを抽出 ということでよろしいでしょうか。 上記推測でよろしければ、以下の方法でできます。 (方法1はクエリのみの対応で済むが抽出速度が鈍化、 方法2は抽出が比較的早いがマクロ又はVBAが必要) 【方法1】クエリにOr条件を追加する 1)当該クエリをデザインビューで開く 2)空白になっている『フィールド』欄に、以下の式を入力 IsNull([Forms]![作表条件]![日付1] & [Forms]![作表条件]![日付2]) ※入力を終了すると、先頭に「式1: 」が追加されます。 3)今追加した列の『表示』チェックボックスをオフに設定 4)『日付』フィールドに指定している「Between Nz(~)」の すぐ下の枠に「Is Null」を入力 5)「2」で追加した列の、「Between Nz(~)」と同じ行に 「False」を入力 6)同じく列の、「Is Null」を入力したのと同じ行に「True」を 入力 7)クエリを保存して閉じる 【方法2】フォームのレコードソースを差し替える 現在作成済みのクエリの他に、新たに、『日付』フィールド の抽出条件に「Is Null」を指定したクエリを作成しておいて 下さい。 これを、マクロ又はVBAで、フォームのレコードソースとして 使用します。 ※マクロなら『値の代入』アクションで、『式』にクエリ名を、 『アイテム』に「[Forms]![作表条件].[RecordSource]」を 指定します。 VBAで、当該フォームへの記述なら、「Me.RecordSource」 でもOkです。 (これについては、必要なようでしたら補足説明します: その際はマクロ/VBAどちらを使用しているかお報せ下さい) ・・・以上です。
お礼
具体的なご返答誠にありがとうございます。 希望の動作は 少なくとも一方が空白以外なら指定範囲のものを抽出 双方が空白なら『日付』がNullを含むすべてのものを抽出 ということです。 説明不足ですいません。 結局、良く考えたら日付は必要なので、必須入力項目にしてNULL値を許さない方向で考えたいと思います。 ただ、参考のために、よろしければVBAを使った方法についてもう少し詳しく補足いただけませんでしょうか?
- MRT1452
- ベストアンサー率42% (1391/3293)
#2です。 UNIONを使えばと書きましたが、確かにNo3の方のように段階を踏むというやりかたでも良いと思います。 あまりデータベースの扱いになれていないのであればNo3の方のやり方の方が視覚的にわかりやすいでしょう。 Accessですので、クエリを組み合わせて実現することも可能です。 つまり、 (1)NULLの物だけを集めたクエリ (2)日付範囲を集めたクエリ (3)(1)と(2)をくっつけるクエリ フォームは(3)を参照 というやり方もあります。No3の方の考え方だと (1)NULLの物だけを集め、テーブルにINSERT(UPDATE)するクエリ (2)日付範囲を集め、テーブルにINSERT(UPDATE)するクエリ で、フォームはクエリではなくテーブルのフィールドを参照。 という感じになりますかね。 蛇足ではありますが。 Accessは正直言って、一部、特殊なSQL記法を使うので、 Accessのやり方はOravleやPostgreSQLなどを扱う際に使えない事があるので。 もしAccess以外のDBを使うことになったら注意してください。 この辺はAccessがプログラム開発とデータベースをごちゃ混ぜにした形で、 そこを利便化させるために独自の手法を取る事ができるので。 Accessではクエリ等から簡単にフォームのフィールドに連携」させられますが、 一般的なDBではDBとプログラムは切り離されているので、 その辺の処理を作りこんだりしないといけません。 その反面、プログラムとDBの組み合わせの自由度が高いです。 また、Accessはセキュリティ面や、データロックといったような多重アクセス制御、 バックアップ等のデータ保守というのが非常に苦手なので、 重要性を伴うアプリケーション開発や、 多人数が扱うシステムには通常Accessは使いません。 Accessを使うにしても上記のOracle等を組み合わせて使います。 (AccessのテーブルやSQLを一時的なものとして使う) ご参考まで。
お礼
いろいろとご指南ありがとうございます。 SQLやORACLEもそのうち使えるようになりたいものです。
- layy
- ベストアンサー率23% (292/1222)
いったんテーブルに出力して、追加します。2段階操作。でも可能です。 ユニオンクエリは結果がどうなるかほかより見えにくいかと思います。条件間違うと膨大です。使えば便利ですが。 ユニオンクエリの使い方が理解できてない、馴れない最初なら、手順面倒でもクエリデザインで確認しながら順次結果を出すのもいいでしょう。 たまたまうまくいった、で終わらせるのは良くないですから。
お礼
度々のご返答ありがとうございます。 参考にさせていただきます。
- MRT1452
- ベストアンサー率42% (1391/3293)
No1の方が書かれているように、 NULLのデータと、範囲指定のデータをUNIONでくっつける形になると思います。 BETWEENはあくまで範囲指定ですので値でも何でもないNULLは拾えません。 また、「空白」と「NULL」はまったく別物です。 (空白は本当に長さ0の値ですが、NULLは何の値が入っているか分からない。(NULLという何らかのデータ)) 開発環境等によっては、一緒くたに判定してくれる場合もありますが。 別物として扱うクセをつけましょう。
お礼
ご回答ありがとうございます。 UNIONですかー。 ちょっと敷居が高いので今までやった事ありませんでした。 チャレンジしてみます。 また、恥ずかしながら「空白」=「NULL」と理解していました。 ご指摘ありがとうございます。
- layy
- ベストアンサー率23% (292/1222)
「日付」が NULLで抽出したもの と NULL以外でー、BETWEEN使って抽出したもの これらが合わさればいいのでは?、どうですか?。 NULLの分までBETWEEN使ってなんとか抽出しようとしてますか。
お礼
ご返答ありがとうございます。 NULLの分までBETWEENで抽出しようとはしていませんが、どうしたらいいのかわからず困っていました。
お礼
詳しくご説明いただきありがとうございます。 早速参考にさせてもらいます。