• ベストアンサー

Access2000で重複データに・・・

Access2000の重複データの処理について質問です。 あるフィールドの重複レコードを検索し、該当するレコードの別フィールドに「●」をつけようとしています。ただ、重複する最初のレコードには「●」をつけたくないのです。 例えば  aaa ・・・ (1)  bbb  aaa ・・・ (2)  ccc  aaa ・・・ (3)  eee というフィールドだった場合、(1)には「●」をつけずに(2)以降にのみつけたいのです。 重複クエリで重複レコードを抽出して重複テーブル作成→重複テーブルと元テーブルを組み合わせて更新クエリ作成という方法でやったのですが、そうすると(1)にも「●」がついてきます。(当然ですが・・・) 何か名案があれば教えてください。 やはり、VBAを使わないと無理でしょうか・・・?

質問者が選んだベストアンサー

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.7

>頭の中で理屈は理解しているつもりなのですが、 >クエリの組み方が悪いのか、うまく抽出できません。 >すでにDateAddでつまづいてます・・・。 理解しやすさを狙って処理を追加していったので 逆にぐしゃぐしゃになっちゃいましたかね。 じゃ、すっきりさせましょか。 いままでの抽出条件を別の文章で言い換えると、 「一番古い日付のレコードの次から3ヶ月未満のレコードを更新対象とする」 ということになります。 なんで、こんなフィールドを持つ集計クエリを作ってみましょう。 ・重複項目 ・一番古い日付 ・一番古い日付から3ヵ月後 上の2つはもう作っているのでOKだと思いますが、一番下は、次のように記述する必要があります 新しいフィールドの名前:DateAdd('m', 3, min(日付のフィールド名)) で、種類を演算にしておきます。 これでクエリを実行すると、3ヵ月後の日付が追加されたレコード内容が表示されるはずです。 あとは、次の条件で元のテーブルと組み合わせたクエリを作ります。 ・テーブルの重複項目とクエリーの重複項目を線で結ぶ ・テーブルの日付項目の抽出条件は一番古い日付のレコードの次から3ヶ月未満 上の条件は問題ないと思います。 ちなみに下の抽出条件にはこんな感じに書きます。 >[テーブル名].[一番古い日付] And <[クエリ名].[3ヵ月後の日付] これで、対象データが絞り込めるはずです。 あとはこれを更新クエリにすればOKでしょう。 興味がありましたら、SQLビューでSQL文も見てみてください。 おそらく、ghepardo25さんなら、書いてある意味がなんとなくでもわかるはずですよ。 SQLがわかるようになると、ちょっと条件が複雑なクエリは 自分でSQLを書いた方が速く出来ますよ。

ghepardo25
質問者

お礼

まさに思い通りのデータ処理ができました!丁寧な説明に感謝感激です。 最後まで見捨てずアドバイスくださってありがとうございます m(__)m SQLも徐々に勉強していくつもりです。また何か困ったことができたときは、よろしくお願いします。 ありがとうございました。

ghepardo25
質問者

補足

ごめんなさい。私の勘違いで、条件がまだありました。 上のoshiete_kunさんの補足にある例を見て頂きたいのですが、---の下の部分の条件も必要なのです。taka_tetsuの教えてくれたクエリも、今までの私の解釈も、----の下の部分はすべて●なしになるんですよね。だけどそれではダメだということにさっき気づきました。 すみません。何度も何度も追加・変更で・・・。

その他の回答 (10)

noname#27115
noname#27115
回答No.11

> 今日を基準に3ヶ月ではなく、最初のレコードが登場した日から3ヶ月 この条件に下のは当てはまらない気がするのですが、、下のはどういう条件で抽出されるのでしょうか? 3ヶ月以降でも一定期間をおくと抽出するのでしょうか? ---------------- 2003/08/02 AAAA ● 2003/09/22 AAAA ● 2003/10/12 AAAA ● 2003/11/25 AAAA  2003/12/14 AAAA ●

ghepardo25
質問者

補足

>3ヶ月以降でも一定期間をおくと抽出するのでしょうか? そうなのです。 3ヶ月以降の重複はいったん「●」をはずすのですが、次はそのはずしたレコードを起点に3ヶ月以内の重複に「●」をつけ、また3ヶ月以上後のレコードではずし・・・というのを繰り返したいのです。 最初の質問とずい分条件が違ってきましたので、ここは一応締め切りとし、新しく質問し直させて頂きました。 新しい質問先は以下URLです。 色々とお手数をおかけしました。以下の質問先で、引き続きご回答いただければうれしいです。 よろしくお願いします。 http://oshiete1.goo.ne.jp/kotaeru.php3?q=689629

noname#27115
noname#27115
回答No.10

' まったく、勘違いしていました。修正します。 ' 他にもスマートな書き方があるかもしれませんが、とりあえず・・・ ' test1() の変更点(If ~ End If を上書き)    If myRS.RecordCount > 0 Then       Do While Not myRS.EOF         test2 myRS!fld氏名, DMin("fld日付", "tbl社員", "fld氏名 ='" & myRS!fld氏名 & "'")         myRS.MoveNext       Loop    End If ' test2 の変更点(Sub test2 ~ SQL 全体までを上書き) Sub test2(pfld氏名 As String, pfld日付 As Date)   Dim myCN As ADODB.Connection   Dim myRS As ADODB.Recordset   Dim SQL As String     SQL = "SELECT * FROM tbl社員 WHERE (fld氏名='" & pfld氏名 & "') "     SQL = SQL & "AND (fld日付 Between #" & pfld日付 & "# "     SQL = SQL & "AND #" & DateAdd("m", 3, pfld日付) & "#) ORDER BY fld日付 ASC"

ghepardo25
質問者

お礼

更新されました。ありがとうございます。

noname#27115
noname#27115
回答No.9

10/26日より前3ヶ月を処理してみたんですが。。。 こういうことではなかったんでしょうか? もし、 taka_tetsu さんので、解決しているようなので、、うちのはとりあえず、こういう考え方もできるというサンプルで、、、taka_tetsuさんのを採用してください。 それで、うちのコードでもし質問があるようでしたら、続けてお願いします。 >プログラムを実行して砂時計になったマウスポイントが矢印に戻るまで待って レコード数が多くて、VBAでループさせるとそうなりますね。こういう場合、クエリの方が処理は速いですね。 AAAA 2003/07/26 AAAA 2003/07/26 ● AAAA 2003/08/16 ● AAAA 2003/08/17 ● AAAA 2003/08/25 ● AAAA 2003/08/29 ● AAAA 2003/09/07 ● AAAA 2003/09/13 ● AAAA 2003/09/18 ● AAAA 2003/09/25 ● AAAA 2003/09/29 ● AAAA 2003/09/30 ● AAAA 2003/10/05 ● BBBB 2003/08/25 BBBB 2003/09/02 ● BBBB 2003/09/08 ● CCCC 2003/08/11 CCCC 2003/08/11 ● CCCC 2003/08/22 ● CCCC 2003/08/25 ● CCCC 2003/08/28 ● CCCC 2003/08/30 ● CCCC 2003/09/01 ● CCCC 2003/09/11 ● CCCC 2003/09/14 ● CCCC 2003/09/18 ● CCCC 2003/09/19 ● CCCC 2003/09/29 ● DDDD 2003/08/11 DDDD 2003/08/11 ● EEEE 2003/08/02 EEEE 2003/08/02 ● EEEE 2003/08/17 ● EEEE 2003/10/02 ● FFFF 2003/08/22 FFFF 2003/08/22 ● FFFF 2003/09/23 ● GGGG 2003/08/17 GGGG 2003/08/17 ● GGGG 2003/08/19 ● GGGG 2003/09/22 ● HHHH 2003/08/02 HHHH 2003/08/02 ● FFFF 2003/08/09 FFFF 2003/08/09 ● FFFF 2003/08/25 ● FFFF 2003/09/21 ● FFFF 2003/09/30 ● GGGG 2003/08/17 HHHH 2003/08/02 IIII 2003/08/02 ● IIII 2003/08/16 ● IIII 2003/09/18 ● IIII 2003/09/20 ● IIII 2003/10/04 ●

ghepardo25
質問者

補足

レコード数は3000件ぐらいです。(毎月400件ずつぐらい増えていく見込みです) 最初の質問の仕方が悪かったのですが、今日を基準に3ヶ月ではなく、最初のレコードが登場した日から3ヶ月という意識です。(下のような感じです) 2003/04/30 AAAA  2003/04/31 AAAA ● 2003/05/22 AAAA ● 2003/06/01 AAAA ● 2003/07/28 AAAA ● 2003/08/02 AAAA  2003/05/05 BBBB  2003/08/06 BBBB  2003/11/10 BBBB 2003/07/04 CCCC ---------------- 2003/08/02 AAAA ● 2003/09/22 AAAA ● 2003/10/12 AAAA ● 2003/11/25 AAAA  2003/12/14 AAAA ● と、これを書いていて重大なことに気がつきました! 私の課題の解釈が間違っていて、taka_tetsuさんのやり方では解決しない部分がでてきました。taka_tetsuさんのやり方だと、----の上の部分までで、―私もそれでいいと思っていたのですが―、よく考えると---の下の部分も必要なのです。taka_tetsuの教えてくれたクエリだと、----の下の部分はすべて●なしになるんですよね。しまったぁ!! すみません。自分でも作業の全貌を読み取れてませんでした。ご迷惑をおかけしました。

noname#27115
noname#27115
回答No.8

>正常に更新されているデータとそうでないデータが出てきました。 テーブルのデータってすぐには更新されなくて、、だらだらーと更新されるんですよね。まあ、内部的には更新されていると思うのですけど、表示が遅れるのです。 それのせいではないでしょうか?一度、テーブルを閉じて開いたりするとそのときは確実に更新されていると思います。 それと SQL = "SELECT * FROM tbl社員 WHERE fld氏名='" & pfld氏名 & "' AND fld日付>=#" & DateAdd("m", -3, Date) & "# ORDER BY fld日付" の 最後に ASC をつけて、、 SQL = "SELECT * FROM tbl社員 WHERE fld氏名='" & pfld氏名 & "' AND fld日付>=#" & DateAdd("m", -3, Date) & "# ORDER BY fld日付 ASC" ってしてもらえませんでしょうか? それでダメだったら、また、言ってください。テスト環境のサンプル数が少ないもので見落としている部分があるのかもしれません。

ghepardo25
質問者

補足

プログラムを実行して砂時計になったマウスポイントが矢印に戻るまで待って、それからしばらくしてテーブルを開いても、一旦閉じてしばらく待って再度開いても、やはり更新されていないデータがあります。 ASCをつけて実行してもダメでした。何度も何度もお手間かけてすみません。

noname#27115
noname#27115
回答No.6

>「1つ以上の必要なパラメータの値が設定されていません」 うちでは動いているんですが、、そのエラーはSQLのなかで指定しているオブジェクト名と実際のオブジェクト名が一致していない場合に出ると思います。 推測としては、テーブル名もしくはフィールド名が一致していないのではないかと。。 test1b()はすでに設定してある過去の"●"を初期化している部分なので、その部分全体とtest1()の 5行目の test1bをコメントアウトして、他でエラーがでないか見てもらえませんでしょうか?

ghepardo25
質問者

補足

ご指摘通り、1箇所だけフィールド名を修正するのを忘れていたところがありました。修正して実行すると、プログラムは最後まで行ったようですが、なぜか、正常に更新されているデータとそうでないデータが出てきました。3ヶ月以内のダブリであるにもかかわらず、●がついていないデータが一部あるのです。希望通りの結果になっているデータもあって、その差が何なのか、更新されなかったデータの共通点を色々と探したのですが、見当がつきませんでした。こういうことってあるんでしょうか・・・?

noname#27115
noname#27115
回答No.5

'一つまるまる抜けていた処理があったので追加しました。 'テーブル名はtbl社員 'フィールド名は fld氏名(Text)、 fldチェック(Text)、fld日付(Date) 'これで、お望みの通りいかないでしょうか? 'モジュールにしたのコードを貼り付けて、、test1を実行してみてください。 '--------------------------------------------------------------- Sub test1() Dim myCN As ADODB.Connection Dim myRS As ADODB.Recordset Dim SQL As String test1b SQL = "SELECT DISTINCT fld氏名 FROM tbl社員" Set myCN = CurrentProject.Connection Set myRS = New ADODB.Recordset myRS.Open SQL, myCN, adOpenKeyset, adLockOptimistic If myRS.RecordCount > 0 Then Do While Not myRS.EOF test2 myRS!fld氏名 myRS.MoveNext Loop End If myRS.Close: Set myRS = Nothing myCN.Close: Set myCN = Nothing End Sub '--------------------------------------------------------------- Sub test1b() Dim myCN As ADODB.Connection Dim myCOM As New ADODB.Command Dim SQL As String SQL = "UPDATE tbl社員 SET fldチェック=' '" Set myCN = CurrentProject.Connection myCOM.ActiveConnection = myCN myCOM.CommandText = SQL myCOM.Execute Set myCOM = Nothing End Sub '--------------------------------------------------------------- Sub test2(pfld氏名 As String) Dim myCN As ADODB.Connection Dim myRS As ADODB.Recordset Dim SQL As String SQL = "SELECT * FROM tbl社員 WHERE fld氏名='" & pfld氏名 & "' AND fld日付>=#" & DateAdd("m", -3, Date) & "# ORDER BY fld日付" Set myCN = CurrentProject.Connection Set myRS = New ADODB.Recordset myRS.Open SQL, myCN, adOpenKeyset, adLockOptimistic If myRS.RecordCount > 0 Then myRS.MoveFirst i = 1 Do While Not myRS.EOF If i > 1 Then myRS!fldチェック = "●" myRS.Update End If myRS.MoveNext i = i + 1 Loop End If myRS.Close: Set myRS = Nothing myCN.Close: Set myCN = Nothing End Sub '---------------------------------------------------------------

ghepardo25
質問者

補足

コードを拝借して試してみたところ、test1bの"myCOM.Execute"の部分で「1つ以上の必要なパラメータの値が設定されていません」と表示され、止まってしまいました。 これは一体・・・?

noname#27115
noname#27115
回答No.4

Option Compare Database 'テーブル名はtbl社員 'フィールド名は fld氏名(Text)、 fldチェック(Text)、fld日付(Date) 'これで、お望みの通りいかないでしょうか? 'モジュールにしたのコードを貼り付けて、、test1を実行してみてください。 Sub test1() Dim myCN As ADODB.Connection Dim myRS As ADODB.Recordset Dim SQL As String SQL = "SELECT DISTINCT fld氏名 FROM tbl社員" Set myCN = CurrentProject.Connection Set myRS = New ADODB.Recordset myRS.Open SQL, myCN, adOpenKeyset, adLockOptimistic If myRS.RecordCount > 0 Then Do While Not myRS.EOF test2 myRS!fld氏名 myRS.MoveNext Loop End If myRS.Close: Set myRS = Nothing myCN.Close: Set myCN = Nothing End Sub Sub test2(pfld氏名 As String) Dim myCN As ADODB.Connection Dim myRS As ADODB.Recordset Dim SQL As String SQL = "SELECT * FROM tbl社員 WHERE fld氏名='" & pfld氏名 & "' AND fld日付>=#" & DateAdd("m", -3, Date) & "# ORDER BY fld日付" Set myCN = CurrentProject.Connection Set myRS = New ADODB.Recordset myRS.Open SQL, myCN, adOpenKeyset, adLockOptimistic If myRS.RecordCount > 0 Then myRS.MoveFirst i = 1 Do While Not myRS.EOF If i > 1 Then myRS!fldチェック = "●" myRS.Update End If i = i + 1 Loop End If myRS.Close: Set myRS = Nothing myCN.Close: Set myCN = Nothing End Su

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.3

これまでに作成したクエリは、 ・重複クエリ・・・重複レコードの抽出 ・集計クエリ・・・更新対象外レコードの抽出 ・不一致クエリ・・・対象外のレコードを除いた更新レコードの抽出 ・更新クエリ(不一致クエリから変えたかな?) ですよね。 で、今回は、さらに対象外のレコードを増やしたいということなので、 不一致クエリから、さらに3ヶ月以上後のレコードを新しい不一致クエリーで 対象外にしてあげればいいでしょう。 で、3ヶ月以上のレコードはどうやって抽出するかは、ということで次のようになります 1.一番古いレコードを集計クエリで抽出(既に作成済みですよね) 2. 対象テーブルと1.のクエリから選択クエリを作成し、対象テーブルの日付フィールドの抽出条件には、1.のクエリの一番古い日付+3ヶ月以上を指定します。(3ヵ月後はDateAddで求まります) 3. あとは、1番古い日付のレコードを更新対象から外したクエリと2.のクエリを元に、もう一度不一致クエリを作ってあげれば更新対象のレコードのみ残ります。 こんなかんじでいかがでしょうか? #SQLを直接記述するともう少しシンプルになりますが、あえて使っていませんので ちょっとまどろっこしくなっていますが。

ghepardo25
質問者

補足

頭の中で理屈は理解しているつもりなのですが、クエリの組み方が悪いのか、うまく抽出できません。すでにDateAddでつまづいてます・・・。 ここまで助言してもらって情けない話ですが・・・。もう少し格闘してみます。

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

>1番古いものには●をつけずに2番目以降につけたいということです。 これがあるのでしたら、集計クエリーで日付の最小値がもとまりますので、これと重複クエリーとの不一致クエリーから更新対象が求まりますよね。

ghepardo25
質問者

お礼

補足の訂正です。 >3ヶ月以上後の重複には●をつける ではなく、 3ヶ月以上後の重複は●をはずす です。 欄が違いますが、「補足する」を押してから気づいたもので・・・。

ghepardo25
質問者

補足

思い通りの結果となりました。ありがとうございます。 追加ですが、例えばこれをもとに、 1番古いものには●をつけないで2番目以降の重複にはつける、日付を基準に1番古いものから3ヶ月以上後の重複には●をつけるといった条件になった場合は、どの段階でどういう抽出条件を設定すればいいのでしょう・・・?

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

回答ではないですが。 >ただ、重複する最初のレコードには「●」をつけたくないのです。 RDBのレコードに順番はありません。 order byをつけて、初めて抽出順が決定されます。 重複レコードということなので、どれか1つのレコードだけは「●」がつかないようになればいいのですか? それとも1番目のレコードというのを識別する何かがあるのですか?

ghepardo25
質問者

補足

すみません。説明不足でした。 1番目のレコードを識別するものはあります。 日付のフィールドがあって、日付順にソートしたとき、1番古いものには●をつけずに2番目以降につけたいということです。

関連するQ&A