• 締切済み

VBAでデータベースの構築をしています。

VBAでデータベースの構築をしています。 全く同じフィールドを持つ2つのテーブルがあり、その2つのテーブルを 比較し、重複するレコードのみを3つ目のテーブルに抽出したいのですが、 可能でしょうか? 『重複するレコードを削除する』というのはウェブで検索すると出てくる のですが・・・ よろしくお願いいたします。

みんなの回答

  • DexMachina
  • ベストアンサー率73% (1287/1744)
回答No.10

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)
回答No.9

>おそらくご説明いただいた動作と似てます? いろいろロジックを考えた結果であれば問題ないです。 VBAでやりますというからには、 VBAで(クエリでもできるINSERT、DELETEらそのままの)SQL実行するよりは、 クエリでできないこと、 VBAでないとできないこと、 を実装するのが今後のためになると思います。 応用すれば、テーブルはいくつか出力できるので、 テーブルAとテーブルBをそれぞれ読み込み、 テーブルAだけのレコードのテーブルC出力、 テーブルBだけのレコードのテーブルD出力、 テーブルA、Bの重複レコードのテーブルE出力、 と1回の処理でできるようになります。 ほか実現策もいろいろあります。 エクセルで重複となるデータを求めておいて アクセスで条件に付与してもできます。 比較キーだけテキストファイルに保存してコンペアしても良いです。 重複するレコードを削除できれば、その裏返しの発想で、 残ったレコード=今回削除したいもの、になります。 時間かけてもうちょっと考えてみる=ヒントがみつかる、という事も必要です。 答えを提示したら、その時点で解決、で終わり。その先の応用を考えなくなるケース多いです。 がんばってください。

  • layy
  • ベストアンサー率23% (292/1222)
回答No.8

テーブル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文発行でしょうか??

man_u
質問者

お礼

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であったりけっこうグチャグチャしてます。

  • layy
  • ベストアンサー率23% (292/1222)
回答No.7

例えば、 テーブル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)
回答No.6

COBOLというかマッチングのアルゴリズムがわかれば、本件何ら問題ないので、余裕があればお願いします。

  • layy
  • ベストアンサー率23% (292/1222)
回答No.5

参考) 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両方出力しておく、制御可能です。 お勧めしたいですが、 ロジックが理解できてないと失敗します。

man_u
質問者

お礼

ありがとうございます。 COBOLですか。名前を聞いたことあるだけで全くわからないです。 こういう制御ができれば、というのは少しは思い浮かぶのですが、 いざコードにしようとするとなかなか思うようにいかないですね。

  • air300p
  • ベストアンサー率15% (9/60)
回答No.4

ん? これってAccessだったの? ところで Excelでもテーブル、レコード、フィールドの概念はありますけど・・。

man_u
質問者

お礼

ありがとうございます。 Accessだったんです。

  • DexMachina
  • ベストアンサー率73% (1287/1744)
回答No.3

「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」  などとしています)

man_u
質問者

お礼

ありがとうございます。 推測通りaccessでございます。 細かい説明に画像まで入れていただき ありがとうございます。 試してみます。

  • imogasi
  • ベストアンサー率27% (4737/17069)
回答No.2

>『重複するレコードを削除する』というのはウェブで検索すると出てくる のですが・・・ そっくり丸写しするコードを探しても無理だろう。処理ロジックがどうなるのか、考える力が無ければ、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)その他 誰か良いアイデアがあるかも こう言う思考訓練を得て、コードを書いてみて、行き詰ったら質問というのが、力をつけるもと。

man_u
質問者

お礼

ありがとうございます。 投稿したすぐ後に気付きました。 『access 2000』て入れんの忘れてるわ!と・・・ すみません。 2つのテーブルを結合し、ソートし、上から順に直下の行(レコード)との文字列を比較を し、というようなことは思いついたんですが、(1)のようなやり方があれば 一番快適ですね。

  • air300p
  • ベストアンサー率15% (9/60)
回答No.1

いろいろやり方があるんだろうけど 一番簡単だと思うのは そのレコードのフィールドをすべて & で連結して1つの文字列にしてしまい それを比較して同じかどうかで判断すればいいのでは? ワタシがよくやる手法です レコードの検索は For EACH なんかでやればいいかと・・

man_u
質問者

お礼

ありがとうございます。 フィールドを全て連結!? なんだか難しそうですね。 レコードの検索とかはできるのですが・・・

関連するQ&A

専門家に質問してみよう