- ベストアンサー
ACCESSでの検索方法について
マスタファイル2万件、トランザクションファイル約50件程度のデータベースがあります。 50件のデータを1件1件マスタから検索し(キーは2つ)、あればマスタを修正し、なければマスタに追加するプログラムを作成する場合、どういった方法が良いのでしょうか? 1.Do until トランザクション.eof クエリの実行(約50回) loop 2.Do until トランザクション.eof findで検索(約50回) loop 3.2つともレコードセットを開いて上から順番に検索していく。 分かりづらかったらすみません。方法はこれ位しか思い浮かびませんでした。 ほかにあれば教えて下さい。 1の方法がプログラム的には一番楽なのですが、実行スピードは3なのでしょうか? すみませんがご教授お願いします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
まず参考になる質問を一つ(続き物なので2つ上げています)を見てみてください。 http://www.okweb.ne.jp/kotaeru.php3?q=155505 http://www.okweb.ne.jp/kotaeru.php3?q=161189 で前置きはこの程度として まずトランザクションデータが格納されているファイルをワークテーブルに挿入して 1.マスタテーブルとワークテーブルでキー項目で結合して更新が必要な部分更新する。 2.ワークテーブルにあってマスタテーブルに無いキー項目をもつレコードを抽出(不一致クエリーの応用) 3.2の結果を追加クエリーでマスタテーブルに追加 という方法もありますね。
その他の回答 (2)
- imogasi
- ベストアンサー率27% (4737/17069)
アクセスのコーディングそのものになっていませんのでお気に 召さないかもしれませんが、寝る時間になったので・・・。 レコード数が多いマスターに対し、数が少ないトランザクションのマスター更新では、色々の処理ロジック考えられる(注)が、一般には (1)マスターレコードをキー項目でソート(2)トランザクションレコードを同じキー項目でソート(3)(情報処理試験の解説書に良く出てくる)マッチングのロジックで更新するのが一番早いと思います。 マッチングの処理はご存知でしょうが、 p4:マスターを1レコード読む(キーをK1とする) もしEOFならk1にハイバリューをセット(ハイバリュー例16進F FFF... ) 第1レコード以外はp6へ p5:トランザクションを1レコード読む(キーをK2とする) もしEOFならk2にハイバリューをセット(ハイバリュー例16進F FFF... ) p6:if k1=k2 then goto p1 if k1>k2 then goto p2 if k1<k2 then goto p3 p1: k1がハイバリュ―なら終わり(p7へ) でなければトランザクションでマスターを更新 p2: トランザクションでマスターを作る。 次ぎのトランザクションレコードを読みにいく(p5へ) p3: 次ぎのマスターレコードを読みにいく(p4へ) p7:ファイルをクローズ end 昔大型コンピュターのオフラインバッチ処理のマスター更新の定番 でした。メモリーが少ないコンピュター時代でそれなりの採用理由があったと思います。ソートプログラム(のロジックがメーカー製で優秀で)早かった事も寄与したでしょう。 (注)1例としてマスターを1レコード読むごとに、全トランザクションを舐めて等しいキーのものが見つかると更新するとか。トランザクションが同一キーが2以上あるかでロジックが変わる。ないと仮定して良いなら見つかって後は打ち切って、次ぎのマスターレコードへ行ける。
お礼
回答ありがとうございます。 おっしゃらる通りです。 私が3番目に考えていた方法がそんな感じです。 省略したコーディングを2番目に回答して頂いた方のお礼に書いています。 こんな感じでしょうか? こういったやり方とクエリーを複数回実行するのとではどちらが負荷を掛けずに処理が行えるのか、またどちらが一般的なのかが分かりませんでした。 ご丁寧な回答ありがとうございました。
3の「2つともレコードセットを開いて上から順番に検索していく。」というのはトランザクションを読んでFindかSeekでマスタを検索するっていうやり方でしょうか? でしたら一番遅いと思います。マスタの方が2万件ということでしたらOpen時だけでも時間かかると思いますよ。 どうしても、3の方法でやる場合でしたらキーはPrimaryKeyだけでなくそれぞれインデックスをつけて、 Do Until TRN.EOF Set MST=CurrentDB().OpenRecordset("抽出するSQL文",dbOpenDynaset) If MST.EOF=True Then MST.AddNew Else MST.Edit End If ・ ・ ・ MST.Update MST.Close TRN.MoveNext Loop TRN.Close っていう感じでやります。 上で書いたようにキーの2つのフィールドにインデックスが設定されている場合、1が一番速いように思います。
お礼
回答ありがとうございます。 3の方法ですが、 findもseekも使わず、1件1件上から調べて行く方法を考えてました。 findやseekの場合、トランザクションファイルの件数分だけ行わないといけないですが、1件1件マッチングさせていくと2万件を1回見てやるだけで済むと思ったんです。(説明が分かりづらくてすみません。) 凄い省略して書くと MST = OpenRecordset(マスタ) TRN = OpenRecordset(トランザクション) Do Until TRN.EOF If MST.[キー] = TRN.[キー] then マスタ修正 MST.MoveNext TRN.MoveNext ElseIf MST.[キー] > TRN.[キー] then マスタ新規追加 TRN.MoveNext Else MST.MoveNext End If Loop MST.Close TRN.Close (キーを昇順とした場合です。) (マスタが先にEOFになった場合の処理とかは省略しています。) 合ってるかどうかよく分からないですが、非常に簡単に書くと3はこんな感じのつもりでした。 まず、一番最初の方に答えて頂いたクエリーの方法で試してみます。 ただ条件によってマスタの変更するフィールドが変ってくるので(10箇所位)クエリが30個位になるので条件によってSQLを切り替えるようにしていきたいと思います。 似たようなクエリーが増えるのって嫌じゃないですか? みなさんどうなされているのでしょうか。 どうもありがとうございました。 またよろしくお願いします。
お礼
早速の回答ありがとうございます。 またよろしくお願いします。