- 締切済み
VBAでデータベースの構築をしています。
VBAでデータベースの構築をしています。 全く同じフィールドを持つ2つのテーブルがあり、その2つのテーブルを 比較し、重複するレコードのみを3つ目のテーブルに抽出したいのですが、 可能でしょうか? 『重複するレコードを削除する』というのはウェブで検索すると出てくる のですが・・・ よろしくお願いいたします。
- みんなの回答 (10)
- 専門家の回答
みんなの回答
- DexMachina
- ベストアンサー率73% (1287/1744)
No.3です。 まず、不適切な言葉がありましたこと、お詫びします。 大変失礼致しました。 >No.4 > 下記のような方法でとりあえずは快適に動作しましたが、 > エラく回り道をしている感は否めません。 失礼、「重複」の意味を取り違えていました。 (「テーブルA、テーブルBで一致するレコードがあるもの」と 考えていました) ご質問のパターンでも、クエリやSQL文で対応可能です。 1)テーブルAとテーブルBを結合させたクエリをデザインビュー で開く(→レコードが単純に重複表示される選択クエリ) 2)ツールバーなどから『Σ(集計)』ボタンをクリック 3)クエリに『集計:』行が追加されるので、1レコードに集約 するフィールドについては「グループ化」を指定 →No.8で提示の例では「field2」が該当 4)重複しているかどうかを判定するフィールドについて、 『集計:』行に「カウント」を指定 →同じく提示例では「field1」が該当 5)「カウント」を指定したフィールドの『抽出条件:』行に、 「>1」を指定 (→仮に「5件より多い場合」なら「>5」を指定することに なります) ※重複数のデータの表示が不要な場合は『表示:』の チェックをオフにしておきます。 6)上記クエリをテーブル作成クエリ、又は追加クエリとして 保存 ・・・以上です。 なお、添付画像は、フィールド構成が異なりますが、 こちらで作成したサンプルになります。 この画像のSQL文は、以下の通りです: (SQLビューに切り替えて表示されたものをそのまま貼付) SELECT テーブルA.店舗ID, テーブルA.店舗名, テーブルB.顧客ID INTO 来店一覧 FROM テーブルA INNER JOIN テーブルB ON テーブルA.店舗ID = テーブルB.店舗ID GROUP BY テーブルA.店舗ID, テーブルA.店舗名, テーブルB.顧客ID HAVING (((Count(テーブルB.来店ID))>1)); プログラミングにしても話し言葉にしても、「言語」の習得の 基本は「他人のものをなぞる」ところから始まると思います。 提示したサンプルが基礎を固める手助けとなれば幸いです。
- layy
- ベストアンサー率23% (292/1222)
>おそらくご説明いただいた動作と似てます? いろいろロジックを考えた結果であれば問題ないです。 VBAでやりますというからには、 VBAで(クエリでもできるINSERT、DELETEらそのままの)SQL実行するよりは、 クエリでできないこと、 VBAでないとできないこと、 を実装するのが今後のためになると思います。 応用すれば、テーブルはいくつか出力できるので、 テーブルAとテーブルBをそれぞれ読み込み、 テーブルAだけのレコードのテーブルC出力、 テーブルBだけのレコードのテーブルD出力、 テーブルA、Bの重複レコードのテーブルE出力、 と1回の処理でできるようになります。 ほか実現策もいろいろあります。 エクセルで重複となるデータを求めておいて アクセスで条件に付与してもできます。 比較キーだけテキストファイルに保存してコンペアしても良いです。 重複するレコードを削除できれば、その裏返しの発想で、 残ったレコード=今回削除したいもの、になります。 時間かけてもうちょっと考えてみる=ヒントがみつかる、という事も必要です。 答えを提示したら、その時点で解決、で終わり。その先の応用を考えなくなるケース多いです。 がんばってください。
- layy
- ベストアンサー率23% (292/1222)
テーブルA 「1」「2」「3」「4」の4レコード テーブルB 「1」「1」「3」「5」「6」の5レコード とあった場合 テーブル作成クエリと追加クエリで テーブルC 「1」「A」 「2」「A」 「3」「A」 「4」「A」 「1」「B」 「1」「B」 「3」「B」 「5」「B」 「6」「B」 クロス集計クエリ ヘッダ「 」「A」「B」 --------- 明 細「1」「A」「B」重複 明 細「2」「A」「 」 明 細「3」「A」「B」重複 明 細「4」「A」「 」 明 細「5」「 」「B」 明 細「6」「 」「B」 これはできますか。 ※VBA上でSQL文発行でしょうか??
- layy
- ベストアンサー率23% (292/1222)
例えば、 テーブルA 「1」「2」「3」「4」の4レコード テーブルB 「1」「1」「3」「5」「6」の5レコード とあった場合、 Aの1-Bの1(1つめ)重複 Aの1-Bの1(2つめ)重複 Aの1-Bの3 Aの2-Bの3 Aの3-Bの3重複 Aの3-Bの5 Aの4-Bの5 Aの4-Bの6 終了 となる基本構造のロジックをまず作れば良いです。 あとは判断条件、出力条件、終了条件を確認すればできます。 50行いかないくらいです。 DO~LOOP文とIF文、レコード移動くらいなんですが、 機能要件が固まっていながら書けないならしょうがないです。 クエリにしてもVBAにしても テーブルAとテーブルBの一致するレコードは 1レコード(上記例の3)なのか複数レコード(上記例の1)なのか、 どっちを想定した回答か、両方を満たしている回答かは 確認しておいた方がいいですね。
- layy
- ベストアンサー率23% (292/1222)
COBOLというかマッチングのアルゴリズムがわかれば、本件何ら問題ないので、余裕があればお願いします。
- layy
- ベストアンサー率23% (292/1222)
参考) COBOLでよく使うマッチング(1:1や1:N)のプログラムロジックを VBAで実現したらできます。 COBOLプログラミングでは基本です。 簡単にいうと、 AファイルとBファイルを順番に1レコードずつ読み込んで 比較するキーが、 A=Bのとき、両方にある A<Bのとき、Aにしかない、 A>Bのとき、Bにしかない、 と判断するロジックです。 比較判定のあと、次に読み込むのはAなのかBなのか、 終了タイミングはいつなのか、がポイントです。 AとB両方にあるとき、 Aだけ出力しておく、Bだけ出力しておく、AとB両方出力しておく、制御可能です。 お勧めしたいですが、 ロジックが理解できてないと失敗します。
お礼
ありがとうございます。 COBOLですか。名前を聞いたことあるだけで全くわからないです。 こういう制御ができれば、というのは少しは思い浮かぶのですが、 いざコードにしようとするとなかなか思うようにいかないですね。
- air300p
- ベストアンサー率15% (9/60)
ん? これってAccessだったの? ところで Excelでもテーブル、レコード、フィールドの概念はありますけど・・。
お礼
ありがとうございます。 Accessだったんです。
- DexMachina
- ベストアンサー率73% (1287/1744)
「VBA」「データベース」「フィールド」「テーブル」のキーワードから、 Accessについてのご質問と推測しての回答になります。 (勘違いされている方がいるようなので、念のため) > 2つのテーブルを比較し、重複するレコードのみを3つ目のテーブルに > 抽出したい 「テーブル作成クエリ」または「追加クエリ」で、ご希望の動作を行えます。 a)「テーブル作成」クエリは、抽出実行時にテーブル自体を作成します。 (同名テーブル存在時は、上書き(=既存のテーブルが削除)されます) b)「追加クエリ」は、既存のテーブルにレコードを追加します。 (指定したテーブルが不在の場合は、エラーになります) なお、前者では、作成したテーブルに主キーやリレーションシップ等を 設定しても、上書きによって消されてしまいます。 ですので、フォームでの表示程度にしか使わない(=インデックスなどを 使わない)なら前者、抽出結果を元に検索や抽出を更に行うなら後者が、 それぞれお勧めです。 1)新規クエリをデザインビューで開き、比較対象となる2つのテーブルを 追加 2)比較に使用するフィールド全てについて、一方から他方のテーブルに フィールドをドラッグ&ドロップするなどして、結合線を作成 3)メニューやツールバーなどから、クエリの種類を「テーブル作成クエリ」 や「追加クエリ」に設定 4)作成又はレコードを追加するテーブル名を要求するダイアログが表示 されるので、テーブル名を指定後、『OK』ボタンをクリックしてを閉じる 5)適当な名前をつけて保存 ・・・基本は以上ですが、このときによく問題になるのは、「フィールドの値 がNullの場合は、一致(重複)とみなされない」(=結果、意図した抽出状態 にならない)ということです。 これを回避するには、 a)【初心者にわかりやすいと思われる方法】 それぞれのテーブルを直接使用する代わりに、各テーブルごとに 「Nullのフィールドを適当な値に変換するクエリ(各フィールドにNz関数 を適用して、テキスト型なら「""」(空文字)、数値型なら「0」や「-1」など に変換、と)を作成して、これをレコード比較に使用する b)【SQL文の編集が苦にならない場合】 クエリをデザインビューからSQLビューに切り替えて、On句に指定して いるフィールドを、Nz関数で変換する形に編集 <編集前> ・・・ On TblA.ID = TblB.ID And TblA.氏名 = ・・・ <編集後> ・・・ On Nz(TblA.ID, -1) = Nz(TblB.ID, -1) And Nz(TblA.氏名, "") = ・・・ といった方法を採ることになります。 (添付画像では「テーブルA」等としていますが、ここでは1行に収めるため「TblA」 などとしています)
お礼
ありがとうございます。 推測通りaccessでございます。 細かい説明に画像まで入れていただき ありがとうございます。 試してみます。
- imogasi
- ベストアンサー率27% (4737/17069)
>『重複するレコードを削除する』というのはウェブで検索すると出てくる のですが・・・ そっくり丸写しするコードを探しても無理だろう。処理ロジックがどうなるのか、考える力が無ければ、VBA使いではない。エクセルで「データベースの構築」(大がさ)など出来ない。 余談だが、VBAでなくても、VLOOKUP関数などでも近いことが出来ると思う。 ーーー 本題は、2つのファイルの突合せ問題で (1)両者をキーで各々ソートして、両者をマッチングのアルゴリズムで比較 http://soudan1.biglobe.ne.jp/qa5512095.htmlの私の回答(ただしCSVファイルの質問例) (2)「1方のデータの1行のキーデータ」を軸にして、他シート?のデータを、初めから終わりまで総なめして探す。平均で数*1/2の比較を行う泥臭い方法だがわかりやすい。 全行繰り返す。 (3)「1方のデータの1行のキーデータ」を軸にして、他シート?のキー列データをFindメソッドで探し、見つかれば重複あり。全行繰り返す。 (4)後者のデータをソートしておき、2分法で探索。比較階数は少なくて済む。 (5)あと後者を前者の下行範囲ににコピペ。キーでソートして、重複出現するキーがあるかチェック (6)その他 誰か良いアイデアがあるかも こう言う思考訓練を得て、コードを書いてみて、行き詰ったら質問というのが、力をつけるもと。
お礼
ありがとうございます。 投稿したすぐ後に気付きました。 『access 2000』て入れんの忘れてるわ!と・・・ すみません。 2つのテーブルを結合し、ソートし、上から順に直下の行(レコード)との文字列を比較を し、というようなことは思いついたんですが、(1)のようなやり方があれば 一番快適ですね。
- air300p
- ベストアンサー率15% (9/60)
いろいろやり方があるんだろうけど 一番簡単だと思うのは そのレコードのフィールドをすべて & で連結して1つの文字列にしてしまい それを比較して同じかどうかで判断すればいいのでは? ワタシがよくやる手法です レコードの検索は For EACH なんかでやればいいかと・・
お礼
ありがとうございます。 フィールドを全て連結!? なんだか難しそうですね。 レコードの検索とかはできるのですが・・・
お礼
2度もありがとうございます。 解決しました。 下記のような方法でとりあえずは快適に動作しましたが、 エラく回り道をしている感は否めません。 (1)テーブルAとテーブルBを結合し昇降順にソート (2)最初のレコードと次のレコードを比較 一致すれば次へ、不一致であれば最初のレコードを削除 というのをEOFまで繰り返す (3)一致したレコードが2つレコードとして残る field1 field2 1 aaaa 2 aaaa 3 bbbb 4 bbbb 5 cccc 6 cccc というようなテーブルが出来きました。 (4)上記例でいうfield1の偶数を削除する。 といった具合です。 おそらくご説明いただいた動作と似てます? SQL文発光であったり、DAOであったりけっこうグチャグチャしてます。