- ベストアンサー
ACCESSでの検索方法について
マスタファイル2万件、トランザクションファイル約50件程度のデータベースがあります。 50件のデータを1件1件マスタから検索し(キーは2つ)、あればマスタを修正し、なければマスタに追加するプログラムを作成する場合、どういった方法が良いのでしょうか? 1.Do until トランザクション.eof クエリの実行(約50回) loop 2.Do until トランザクション.eof findで検索(約50回) loop 3.2つともレコードセットを開いて上から順番に検索していく。 分かりづらかったらすみません。方法はこれ位しか思い浮かびませんでした。 ほかにあれば教えて下さい。 1の方法がプログラム的には一番楽なのですが、実行スピードは3なのでしょうか? すみませんがご教授お願いします。
- snowb
- お礼率84% (11/13)
- オフィス系ソフト
- 回答数3
- ありがとう数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/17068)
アクセスのコーディングそのものになっていませんのでお気に 召さないかもしれませんが、寝る時間になったので・・・。 レコード数が多いマスターに対し、数が少ないトランザクションのマスター更新では、色々の処理ロジック考えられる(注)が、一般には (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を切り替えるようにしていきたいと思います。 似たようなクエリーが増えるのって嫌じゃないですか? みなさんどうなされているのでしょうか。 どうもありがとうございました。 またよろしくお願いします。
関連するQ&A
- ExcelVBAでAccessのデータを検索する
Excel VBA で、ADOを用いてAccess のデータを検索するにはどうしたらいいですか。 やりたいこと 検索結果を、Excel のセルにコピーすること。 ソースコード 'MDBファイルに接続します Set db = New ADODB.Connection db.Provider = "Microsoft.Jet.OLEDB.4.0" db.Open "C:\Database\test.mdb" 'レコードセットを開きます Set rs = New ADODB.Recordset 'テーブルを開きます rs.Open "PT_MST", db, adOpenForwardOnly, adLockReadOnly findName = ws.Cells(i, 1) & ws.Cells(i, 2) Do ' rs.Find "[S_NUM]='" & findName & "'" rs.Find rs.Fields(1).name & " Like '20k%'" ← ここで、サポートしていない旨のエラーが出る。 If Not (rs.EOF) Then Debug.Print rs.Fields(1).Value Else Exit Do End If rs.MoveNext Loop Until rs.EOF '閉じる rs.Close db.Close '終了処理 Set rs = Nothing Set db = Nothing どう直したら、検出結果を取得できますか。 ご教示下さい。
- ベストアンサー
- Visual Basic
- アクセスの検索について
For I = 1 To Day(SV月末日付) W検索条件 = "年月日 = #" & DateSerial(Year(SV処理年月), Month(SV処理年月), I) & "#" Q_作成.FindFirst W検索条件 Do Until Q_作成.NoMatch 上記のように日付を検索条件にしているのですが、下に記述した Do Until Q_作成.NoMatchの中を通らないのです。 参照しているクエリーにはレコードは間違いなくあるのですが、通らない原因としてどういったことが考えられるのでしょうか?
- ベストアンサー
- Visual Basic
- access vb の検索をする命令でエラー
access vb の criteria を使用してデータ検索をする命令の箇所でエラーが出る (テスト用データではエラーが出ない) テストを終え本番切り替え時にエラーが出る。 動作環境はWinxp,winvista、win7 access2003とaccessvbで構築したdb 実行時エラー’3265’もどこを見て原因があるかも不明です (Accessデータベースを検索するためAccessのフォームにある Access vbの、(1)ロジックと、(2)エラー表示の内容) (1)ロジック rs2.Open "講座開始日時テーブル",cx,adOpenKeyset,adLockOptimistic criteria = "講座コード ='”& 講座コード & "'" ’講座コードの属性は string rs2.moveFist rs2.find critera, 0 ’<- この命令のところでテスト用プログラムでは ’エラーがでないのに、本番用プログラムでは ’以下のエラーが出て原因が把握できない状態です Do Until rs2.EoF If rs2.EOF Then 講座番号確認区分 = "エラー" ’エラー表示 GoTo enda Else 講座コード = rs2!講座番号 ’データ検索OK GoTo XXX Endif Loop (2)エラー表示 |ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー |Microsoft Visual Basic | 実行時エラー’3265’ | 要求された名前、または序数に対応する項目がコレクションで見つかりません。 | | | 継続 終了(E) デバッグ(D) ヘルプ(H) |ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
- ベストアンサー
- Visual Basic
- Access97VBAでのFilter方法
・初歩的な質問でスミマセン。 Access97のVBAでツマヅキ、何か解決の方法はないかと思い質問させていただきます。 クエリー1を元にして作成した、開いている「フォームA」の「テキスト1」(テキストボックス)の文字列でフィルターをかけたいと思っています。 下記のコードを書き実行するのですが、フィルターがかからずクエリー1のデータがそのまま抽出されてしまいます。 Filterコマンド行の記述が間違っているのでしょうか? * クエリ1に「フォームA」の「テキスト1」ボックスを参照する抽出条件を入れてたのですが、「パラメータが少なすぎます。・・・」のエラーとなるので、この方法で行っています。 * Private Sub コマンド6_Click() Dim stTBL, stFltr As Recordset Dim stQRY As DAO.Recordset Set stQRY = CurrentDb.OpenRecordset("クエリー1") stQRY.Filter = "テキスト1='" & [Forms]![フォームA]![テキスト1] & "'" Set stFltr = stQRY.OpenRecordset stQRY.MoveFirst Do Until stQRY.EOF MsgBox stQRY.Fields("フィールド2") stQRY.MoveNext End If Loop 以上のようなんですが、どうかご指導お願いします。
- ベストアンサー
- その他(データベース)
- 【VBA】DoUntil Loopを1度のみ実行
いつもお世話になっております。 Excel2003を使用しております。 「この条件になるまで続行」というのは Do Until Loop だと思うのですが、 ループをしたくないけれど Do Until Loop を利用したい場合(条件になったら即終了したい) Do Until Flag=True 実行したいこと 実行したいこと2 実行したいこと3 Exit do Loop また、やりたいこととしては、 FlagがTrue になったら、プロシージャから抜けたいと思っています。 その場合は、 Do Until Flag=True 実行したいこと 実行したいこと2 実行したいこと3 Exit do Loop If Flag=True Then Exit sub End if このように、別々?に書く以外に方法はないでしょうか? 出来れば、簡単なIF文で実行できないかと思ったのですが… 話がごちゃごちゃしていて分かりにくいので、質問事項のみまとめますと、 ● 条件になったら終了させる。 これは、Do~Loop 、For Next のみの動作でしょうか? ● ループから抜けると同時にSubを終了させるには、ループの外にIF文を書くしかない? 以上、よろしくお願い致します。
- 締切済み
- Excel(エクセル)
- RDOでrowcountが1以上なのに、EOF!
よく分からない現象が発生して困っています。 SQLServer2005 (9.0.1399) 【?な結果】 sSql = "Select * from ○○マスタ" Set oRst = goRDO_Con.OpenResultset(sSql, rdOpenKeyset, rdConcurReadOnly) Do Until oRst.EOF oRst.MoveNext Loop 上記のような文で、oRst.rowcountを取得すると10件なのに、 oRst.Eofを取得すると最初から常にTrueが返ってきます。 【思い描いている結果】 sSql = "Select * from ○○マスタ" Set oRst = goRDO_Con.OpenResultset(sSql, , rdConcurReadOnly) Do Until oRst.EOF oRst.MoveNext Loop 上記のような文では、oRst.rowcountを取得すると10件で oRst.Eofを取得すると最初はFalseが返ってきます。 他のSQLServerがインストールされている別の端末では、 正常にどちらの文も最初はEOFはFalseなのにも関わらず、 ある端末だけが上記のような結果になります。 どこかSQLServerのインストールがおかしいのかもしれませんが、 全く検討がつきません。 怪しいのは、?な結果が返る端末のホスト名が最初○○で、 その状態でSQLServer\MSSQLEXPRESSをインストール。 その後、ホスト名が△△に変更。SQLServer2005をインストール(上書き) している状況ということです。 どなかた何か情報ありませんでしょうか。。
- 締切済み
- その他(データベース)
- ループ処理の繰り返しについて
お世話になっております。 単純なことで悩んでおります、どなたかわかるかたお願いいたします。 <% DO UNTIL SQLrs.EOF IF a=0 THEN %> 処理1 <% END IF SQLrs.MOVENEXT LOOP %> <% SQLrs.MOVEFIRST DO UNTIL SQLrs.EOF IF b=0 THEN %> 処理2 <% END IF SQLrs.MOVENEXT LOOP %> 上記のような処理順なのですが、問題は MoveFirstで先頭のレコードにもどらないのか、2回目のループ処理がうまく抽出できません。 原因はわかりますでしょうか?
- ベストアンサー
- Microsoft ASP
- Do Untilで途中で抜け出る方法は
Do Until rs.EOF myCtr = myCtr + 1 If myCtr > 5 Then brake End If Debug.Print rs!品番, rs!品名 rs.MoveNext Loop こんな感じでできませんか 実行してみると brakeのところでエラーになります ACCESSの中のVbでADOを使っています
- ベストアンサー
- Visual Basic
- Excel VBA : Accessのデータを検索
Excel VBA を使って、Accessのデータを検索したい。 除外テーブルには「管理ID」レコードが在り、ユニークな番号を登録してあります。 やりたいことは、除外テーブルの管理IDに在るであろう、"E003"の有無を確認したいと思います。 作ってみたソースコードは、以下の通り。 Private Sub aSearch_Click() DB.TableOpen ("db_name.mdb") 'Accessのファイル DB.FindRecode ("E003") ' 検索対象文字列 DB.TableClose End Sub ------------------------------ここから、標準モジュール Public adoCn As ADODB.Connection Public adoRs As ADODB.Recordset Public fSql As String Public fRow As Integer 'データ ソースへの接続と、レコードセットへの接続 Sub TableOpen(ByVal mdb_name As String) Set adoCn = New ADODB.Connection 'データ ソースへの接続 adoCn.Provider = "Microsoft.Jet.OLEDB.4.0" 'Accessへ接続プロバイダ名 adoCn.Open mdb_name '接続するmdbファイル名" fSql = "select 管理ID from 除外テーブル" Set adoRs = New ADODB.Recordset 'レコードセットへの接続 adoRs.Open fSql, adoCn, adOpenKeyset, adLockReadOnly 'クエリーの実行 ' adoRs.Open "除外テーブル", adoCn, adOpenKeyset, adLockReadOnly 'クエリーの実行 End Sub 'レコード(管理ID)の検索 Function FindRecode(ByVal findName As String) As String adoRs.Find adoRs.Fields("管理ID") & "=" & findName '← ここでエラーとなる If adoRs.RecordCount = 0 Then MsgBox "該当するレコードは存在しません" FindRecode = "" Exit Function Else Do ' Doループは、要らないかも??? Debug.Print adoRs.Fields("管理ID") & "/" & adoRs.Fields("登録日") adoRs.MoveNext Loop Until adoRs.EOF End If FindRecode = adoRs.Fields("管理ID") End Function 'データ ソースへの接続と、レコードセットを切断する Sub TableClose() adoRs.Close 'クエリーを閉じる adoCn.Close 'データ接続を閉じる Set adoRs = Nothing Set adoCn = Nothing End Sub ------------- ここまで データのソースから、検索する方法が良く判っておらず、Open / find の使い方はこれで良いのでしょうか。 以上、よろしくお願いします。
- ベストアンサー
- Visual Basic
- Access テーブル内検索を教えてください。
いつもお世話になっております。今回、また皆様のお知恵をお貸しいただきたく思います。 検索対象テーブル:社員マスタ(ユニオンクエリ)複数件 検索値:画面リストボックスより入力された部署コード・BUSYO 処理内容:社員マスタの部署コードに入力値BUSYOが一致している データに【更新処理:(仮)INSERTクエリ】を実行したい。 DLookup()や、FindRecord を調べましたが私の技力は限界です。 どうか、ご教授お願いします。 ■コード(実際チャレンジした一部です。) 'str検索条件を条件にバンドIDをT_メンバーテーブルから検索する strBusyo = DLookup("[部署コード]", "qry_社員マスタ", BUSYO) '結果のテスト表示 If strBusyo = "" Then MsgBox BUSYO& "は、見つかりませんでした" Else qry_社員マスタから条件に合致したデータをテーブルにInsert DoCmd.OpenQuery "qry_追加処理" DoCmd.FindRecord strBusyo 'データを検索する DoCmd.GoToControl "[部署CD]" 'コントロールを[部署CD]へ移動 End If
- 締切済み
- Visual Basic
お礼
早速の回答ありがとうございます。 またよろしくお願いします。