dポイントプレゼントキャンペーン実施中!

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

何か名案があれば教えてください。
やはり、VBAを使わないと無理でしょうか・・・?

A 回答 (11件中1~10件)

>頭の中で理屈は理解しているつもりなのですが、


>クエリの組み方が悪いのか、うまく抽出できません。
>すでにDateAddでつまづいてます・・・。

理解しやすさを狙って処理を追加していったので
逆にぐしゃぐしゃになっちゃいましたかね。

じゃ、すっきりさせましょか。


いままでの抽出条件を別の文章で言い換えると、

「一番古い日付のレコードの次から3ヶ月未満のレコードを更新対象とする」
ということになります。


なんで、こんなフィールドを持つ集計クエリを作ってみましょう。

・重複項目
・一番古い日付
・一番古い日付から3ヵ月後

上の2つはもう作っているのでOKだと思いますが、一番下は、次のように記述する必要があります

新しいフィールドの名前:DateAdd('m', 3, min(日付のフィールド名))
で、種類を演算にしておきます。

これでクエリを実行すると、3ヵ月後の日付が追加されたレコード内容が表示されるはずです。


あとは、次の条件で元のテーブルと組み合わせたクエリを作ります。

・テーブルの重複項目とクエリーの重複項目を線で結ぶ
・テーブルの日付項目の抽出条件は一番古い日付のレコードの次から3ヶ月未満

上の条件は問題ないと思います。
ちなみに下の抽出条件にはこんな感じに書きます。

>[テーブル名].[一番古い日付] And <[クエリ名].[3ヵ月後の日付]

これで、対象データが絞り込めるはずです。

あとはこれを更新クエリにすればOKでしょう。

興味がありましたら、SQLビューでSQL文も見てみてください。
おそらく、ghepardo25さんなら、書いてある意味がなんとなくでもわかるはずですよ。
SQLがわかるようになると、ちょっと条件が複雑なクエリは
自分でSQLを書いた方が速く出来ますよ。

この回答への補足

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

補足日時:2003/10/26 15:01
    • good
    • 0
この回答へのお礼

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

お礼日時:2003/10/25 00:18

> 今日を基準に3ヶ月ではなく、最初のレコードが登場した日から3ヶ月



この条件に下のは当てはまらない気がするのですが、、下のはどういう条件で抽出されるのでしょうか?

3ヶ月以降でも一定期間をおくと抽出するのでしょうか?

----------------
2003/08/02 AAAA ●
2003/09/22 AAAA ●
2003/10/12 AAAA ●
2003/11/25 AAAA 
2003/12/14 AAAA ●

この回答への補足

>3ヶ月以降でも一定期間をおくと抽出するのでしょうか?

そうなのです。
3ヶ月以降の重複はいったん「●」をはずすのですが、次はそのはずしたレコードを起点に3ヶ月以内の重複に「●」をつけ、また3ヶ月以上後のレコードではずし・・・というのを繰り返したいのです。

最初の質問とずい分条件が違ってきましたので、ここは一応締め切りとし、新しく質問し直させて頂きました。
新しい質問先は以下URLです。

色々とお手数をおかけしました。以下の質問先で、引き続きご回答いただければうれしいです。

よろしくお願いします。

http://oshiete1.goo.ne.jp/kotaeru.php3?q=689629

補足日時:2003/10/26 20:04
    • good
    • 0

' まったく、勘違いしていました。

修正します。
' 他にもスマートな書き方があるかもしれませんが、とりあえず・・・

' 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"
    • good
    • 0
この回答へのお礼

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

お礼日時:2003/10/26 20:04

10/26日より前3ヶ月を処理してみたんですが。

。。

こういうことではなかったんでしょうか?

もし、 taka_tetsu さんので、解決しているようなので、、うちのはとりあえず、こういう考え方もできるというサンプルで、、、taka_tetsuさんのを採用してください。

それで、うちのコードでもし質問があるようでしたら、続けてお願いします。


>プログラムを実行して砂時計になったマウスポイントが矢印に戻るまで待って

レコード数が多くて、VBAでループさせるとそうなりますね。こういう場合、クエリの方が処理は速いですね。


AAAA2003/07/26
AAAA2003/07/26●
AAAA2003/08/16●
AAAA2003/08/17●
AAAA2003/08/25●
AAAA2003/08/29●
AAAA2003/09/07●
AAAA2003/09/13●
AAAA2003/09/18●
AAAA2003/09/25●
AAAA2003/09/29●
AAAA2003/09/30●
AAAA2003/10/05●

BBBB2003/08/25
BBBB2003/09/02●
BBBB2003/09/08●

CCCC2003/08/11
CCCC2003/08/11●
CCCC2003/08/22●
CCCC2003/08/25●
CCCC2003/08/28●
CCCC2003/08/30●
CCCC2003/09/01●
CCCC2003/09/11●
CCCC2003/09/14●
CCCC2003/09/18●
CCCC2003/09/19●
CCCC2003/09/29●

DDDD2003/08/11
DDDD2003/08/11●

EEEE2003/08/02
EEEE2003/08/02●
EEEE2003/08/17●
EEEE2003/10/02●

FFFF2003/08/22
FFFF2003/08/22●
FFFF2003/09/23●

GGGG2003/08/17
GGGG2003/08/17●
GGGG2003/08/19●
GGGG2003/09/22●

HHHH2003/08/02
HHHH2003/08/02●

FFFF2003/08/09
FFFF2003/08/09●
FFFF2003/08/25●
FFFF2003/09/21●
FFFF2003/09/30●

GGGG2003/08/17

HHHH 2003/08/02

IIII 2003/08/02●
IIII2003/08/16●
IIII2003/09/18●
IIII2003/09/20●
IIII2003/10/04●

この回答への補足

レコード数は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の教えてくれたクエリだと、----の下の部分はすべて●なしになるんですよね。しまったぁ!!
すみません。自分でも作業の全貌を読み取れてませんでした。ご迷惑をおかけしました。

補足日時:2003/10/26 14:21
    • good
    • 0

>正常に更新されているデータとそうでないデータが出てきました。



テーブルのデータってすぐには更新されなくて、、だらだらーと更新されるんですよね。まあ、内部的には更新されていると思うのですけど、表示が遅れるのです。

それのせいではないでしょうか?一度、テーブルを閉じて開いたりするとそのときは確実に更新されていると思います。

それと

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"

ってしてもらえませんでしょうか?

それでダメだったら、また、言ってください。テスト環境のサンプル数が少ないもので見落としている部分があるのかもしれません。

この回答への補足

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

補足日時:2003/10/25 23:27
    • good
    • 0

>「1つ以上の必要なパラメータの値が設定されていません」



うちでは動いているんですが、、そのエラーはSQLのなかで指定しているオブジェクト名と実際のオブジェクト名が一致していない場合に出ると思います。

推測としては、テーブル名もしくはフィールド名が一致していないのではないかと。。

test1b()はすでに設定してある過去の"●"を初期化している部分なので、その部分全体とtest1()の 5行目の test1bをコメントアウトして、他でエラーがでないか見てもらえませんでしょうか?

この回答への補足

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

補足日時:2003/10/24 23:59
    • good
    • 0

'一つまるまる抜けていた処理があったので追加しました。



'テーブル名は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
'---------------------------------------------------------------

この回答への補足

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

補足日時:2003/10/23 22:22
    • good
    • 0

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
    • good
    • 0

これまでに作成したクエリは、


・重複クエリ・・・重複レコードの抽出
・集計クエリ・・・更新対象外レコードの抽出
・不一致クエリ・・・対象外のレコードを除いた更新レコードの抽出
・更新クエリ(不一致クエリから変えたかな?)

ですよね。

で、今回は、さらに対象外のレコードを増やしたいということなので、
不一致クエリから、さらに3ヶ月以上後のレコードを新しい不一致クエリーで
対象外にしてあげればいいでしょう。


で、3ヶ月以上のレコードはどうやって抽出するかは、ということで次のようになります
1.一番古いレコードを集計クエリで抽出(既に作成済みですよね)

2. 対象テーブルと1.のクエリから選択クエリを作成し、対象テーブルの日付フィールドの抽出条件には、1.のクエリの一番古い日付+3ヶ月以上を指定します。(3ヵ月後はDateAddで求まります)

3. あとは、1番古い日付のレコードを更新対象から外したクエリと2.のクエリを元に、もう一度不一致クエリを作ってあげれば更新対象のレコードのみ残ります。


こんなかんじでいかがでしょうか?


#SQLを直接記述するともう少しシンプルになりますが、あえて使っていませんので
ちょっとまどろっこしくなっていますが。

この回答への補足

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

補足日時:2003/10/23 22:15
    • good
    • 0

>1番古いものには●をつけずに2番目以降につけたいということです。



これがあるのでしたら、集計クエリーで日付の最小値がもとまりますので、これと重複クエリーとの不一致クエリーから更新対象が求まりますよね。

この回答への補足

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

補足日時:2003/10/22 16:56
    • good
    • 0
この回答へのお礼

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

お礼日時:2003/10/22 17:06

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!