Access VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


125 / 2272 ツリー ←次へ | 前へ→

【12923】カレントレコードのサブIDが前のレコードのサブIDと同じなら まるこ 16/1/15(金) 16:25 質問[未読]
【12924】Re:カレントレコードのサブIDが前のレコー... かるびの 16/1/16(土) 3:12 回答[未読]
【12925】Re:カレントレコードのサブIDが前のレコー... かるびの 16/1/16(土) 13:02 回答[未読]
【12927】Re:カレントレコードのサブIDが前のレコー... まるこ 16/1/17(日) 0:19 発言[未読]
【12928】Re:カレントレコードのサブIDが前のレコー... まるこ 16/1/18(月) 13:12 発言[未読]
【12929】Re:カレントレコードのサブIDが前のレコー... まるこ 16/1/18(月) 13:15 発言[未読]
【12930】Re:カレントレコードのサブIDが前のレコー... まるこ 16/1/18(月) 13:28 発言[未読]
【12936】Re:カレントレコードのサブIDが前のレコー... まるこ 16/2/5(金) 13:57 お礼[未読]

【12923】カレントレコードのサブIDが前のレコード...
質問  まるこ  - 16/1/15(金) 16:25 -

引用なし
パスワード
   こんにちは初めまして

下記のようなクエリを作成したいと思っていますが、なかなか上手くいかずお知恵を借りたくてお邪魔しました
(カレントレコードのサブIDが前のレコードのサブIDと同じなら区分フィールドは空白、違っていたら*を入れたい)

ID  |サブID|名前   |区分
301245|4500 |かきくけこ|* 
301246|4500 |まみむめも|
301247|5000 |らりるれろ|*
301248|3500 |あいうえお|*

やってみたこと:

連番1というフィールドを作成し、DCount("証憑No","クエリA","サブID <= '" & [サブID] & "'")
連番2というフィールドを作成し、DCount("証憑No","クエリA","ID<=" & [ID])
として同じレコードの二つの値を比較しイコールなら*イコールでないならNullとしようとしました

IDはユニークでサブIDはユニークではありません。

こうなります

ID  |サブID|名前   |連番1|連番2|区分 |
301245|4500 |かきくけこ|182 |181 |   | 正解は*   
301246|4500 |まみむめも|182 |182 |*   | 正解はNull 
301247|5000 |らりるれろ|183 |183 |*   | 正解は* 
301248|3500 |あいうえお|181 |184 |   | 正解は*      

サブIDは例を見て頂いたらわかるとおり順番が昇順でも降順でもなくバラバラなんですよね・・・
だけどIDの昇順にしたいし、独自の番号ではなく与えられるものなので変更ができないんです
これはダメだと気付きましたがお手上げです
なにか良い方法はないでしょうか?

【12924】Re:カレントレコードのサブIDが前のレコ...
回答  かるびの  - 16/1/16(土) 3:12 -

引用なし
パスワード
    アクセスでは、あるレコードの値が他のレコードの値によって決まる
というような計算結果を表示するのは、苦手です。
 今回の場合、前のレコードの値によって区分フィールドの値が決まるわけであり、アクセスが苦手とするパターンのものにほかなりません。


 今回の場合、あるレコードについて、その「前のレコード」を取得できれば、
御希望のことができます。
 では、どうやって「前のレコード」を取得するかです。

 リレーショナルデータベースでは、テーブルにはレコードの並び順の情報を
持ちません。
 したがって、あるレコードを基準として「一つ前のレコード」とか、
「二つ後のレコード」とかということでは、レコードを特定できません。

 リレーショナルデータベースでは、レコードの特定は主キーによってなされます。
 したがって、今回の場合、「前のレコード」の主キーの値を
計算によって求められれば、希望のことができるということになります。


 主キーの値が連番であるということが保証されているのであれば、簡単です。
 あるレコードについて、その「前のレコード」の主キーの値は、
あるレコードの主キーの値から1を引くことにより求められます。

 ただ、主キーの値が必ず連番になっているというような事態は、
奇跡的な偶然の産物といってよいほどの事態です。
 というのは、あるレコードがテーブルから削除されれば、
主キーは連番ではなくなってしまうところ、
レコードの削除は、テーブルを長く使っていれば、ほとんど場合で少なくとも1度は行うはずであり、
将来を見越しても、少なくと1度はほぼ必ずレコードの削除をするはずだからです。
 そのため、主キーの値が連番となっているという事態は、ほぼ期待できません。

 
 主キーが連番であることが期待できないなら、
レコードごとに必ず値が異なり(これはしばしば「ユニークな」とか「一意の」とかと表現されます)、
かつ、連番となるフィールドを設けてあげられれば、解決します。


 具体的には、

ID  |サブID|名前   
301245|4500 |かきくけこ 
301246|4500 |まみむめも
301247|5000 |らりるれろ
301248|3500 |あいうえお

というテーブルに対して、連番のフィールドを持つクエリを作ります。
 まるこさんの「連番2」フィールドがそのような連番のフィールドに該ります。
そうすると、そのクエリは次のようなものになります。

ID  |サブID|連番2
301245|4500 |181 
301246|4500 |182 
301247|5000 |183 
301248|3500 |184 

 なお、このクエリを「クエリ甲」と呼ぶことにします。


 クエリ甲から、連番2の値から1を引いた値を持つ演算フィールドを持つクエリを作ります。
 このクエリは、「クエリ乙」と呼ぶことにします。
 次のようなクエリになります。

ID  |サブID|連番2|連番2引く1
301245|4500 |181 |    180
301246|4500 |182 |    181
301247|5000 |183 |    182
301248|3500 |184 |    183


 さらに、クエリ乙とクエリ乙とを結合させるクエリ(クエリ丙)を作ります。
 結合フィールドは、「連番2引く1」フィールドと「連番2」フィールドとします。
 なお、このようなクエリは「自己結合クエリ」と呼ばれます。

 クエリ乙        | クエリ乙_2
ID  |サブID|連番2引く1|連番2|ID  |サブID
301245|4500 |    180|   |   |
301246|4500 |    181| 181|301245|4500  
301247|5000 |    182| 182|301246|4500 
301248|3500 |    183| 183|301248|3500

 
 次に、「クエリ乙.サブID」フィールドと「クエリ乙_2.サブID」フィールドとを
比較する演算フィールドを持つクエリを作ります。
 この演算フィールドはIIF関数を使って式を組みます。
 そうすると、次のようなクエリになります。

 クエリ乙        | クエリ乙_2    |
ID  |サブID|連番2引く1|連番2|ID  |サブID|区分
301245|4500 |    180|   |   |   | *
301246|4500 |    181| 181|301245|4500 | 
301247|5000 |    182| 182|301246|4500 | * 
301248|3500 |    183| 183|301248|3500 | *


 考え方としては、上記のとおりなのですが、最大の問題点は速度です。

 DCount関数やDSum関数などは、D系関数と呼ばれたりしますが、
D系関数をクエリの演算フィールドで使うと、激遅となり、実用に堪えないと言われています。
 実際に私もそれを経験しました。
 なお、激遅になるかどうかは、
パソコンの性能とテーブルのレコード数次第であり、
高性能のパソコンでは実用に堪えるかもしれません。
 

 私のパソコンでは、激遅になってしまうので、
私がやるなら、上記のようなクエリは組みません。

 私がやるなら、次のような方法をとります。
 すなわち、
予めテーブルに「区分」フィールドを設けた上で、
テーブルのレコードセットを取得し、
これをループさせ、
各ループにおいて、前レコードと比較して、「区分」フィールドに値を書き込む
という方法を取ります。

 この方法だと、上記のようなクエリよりもはるかに速いです。

 もっとも、この方法は、VBA必須です。

【12925】Re:カレントレコードのサブIDが前のレコ...
回答  かるびの  - 16/1/16(土) 13:02 -

引用なし
パスワード
    私の前レスの
> 私がやるなら、次のような方法をとります。
> すなわち、
>予めテーブルに「区分」フィールドを設けた上で、
>テーブルのレコードセットを取得し、
との部分についての補足ないし訂正です。


 まず、「テーブルのレコードセットを取得し、」ですが、正確に言うと、
「テーブルのレコードについて並び替えを指定したクエリのレコードセットを取得し、」
です。


 次に、「予めテーブルに「区分」フィールドを設けた上で、」についてです。

 「区分」フィールドを設けるのも一つの方法なのですが、
テーブルに設けるのは「区分」フィールドではなく、
「連番」フィールドにした方が使い勝手がいいかもしれません。 

 というのは、第一に、
「前のレコード」と比較したいという場面は、今回の「区分」フィールド以外にも
出てきそうなので、そうなった場合、連番フィールドがあると対応しやすいからです。

 第二に、「区分」フィールドの値は、特定の並び順の下でのみ妥当する値であり、
つまり、並び替え方が変われば、「区分」フィールドの値は異なってくるはずなので、
それを恒久的にテーブルに保持するというのは、良くないのではないかと思うからです。

 第三に、テーブルの「連番」フィールドであれば、それが暫定的な値、
つまり、特定の並び順の下でのみ妥当する値だということに気付きやすいからです。


 それから、前レスで触れた自己結合クエリの作り方について述べておきます。

 まず、クエリのデザインビューを開きます。
 そして、「テーブルの表示」というウィンドウを表示させます
(2003であれば、メニューの「クエリ(Q)」→「テーブルの表示(H)」を実行します)。
 「テーブルの表示」ウィンドウから「クエリ乙」を選択します。
すると、デザインビュー中に「クエリ乙」という標題のボックスが表示されます。
 次に、再度、「テーブルの表示」というウィンドウを表示させ、「クエリ乙」を選択します。
すると、デザインビュー中に「クエリ乙_1」という標題のボックスが表示されます。
 あとは、「クエリ乙」や「クエリ乙_1」から適宜フィールドを選択して、クエリ丙を作ります。

【12927】Re:カレントレコードのサブIDが前のレコ...
発言  まるこ  - 16/1/17(日) 0:19 -

引用なし
パスワード
   かるびの様
ご回答ありがとうございます
なかなか難しいのですね
確かにレコードは削除しまくりです
じっくり読ませて頂いて頑張ってやってみます

時間かかるかもしれませんが必ず結果を報告に参ります
ありがとうございました

【12928】Re:カレントレコードのサブIDが前のレコ...
発言  まるこ  - 16/1/18(月) 13:12 -

引用なし
パスワード
   かるびの様

回答いただいたのを参考に
下記コードを作ってみましたが、いきなり詰まっています。うまく動きません
おかしいところをご指摘いただけませんでしょうか?

Private Sub ボタン_Click()
Dim db As DAO.Database
Set db = CurrentDb
Dim rs As DAO.Recordset

 DoCmd.OpenQuery "AQ_クエリA" ・・・・クエリAが書き込み不可能の為テーブルAを作成するためのアクションクエリ(テーブルAが作成されます)
 Set rs = db.OpenRecordset(テーブルA)・・・・※エラー箇所 「入力テーブルまたはクエリ"が見つかりませんでした。そのテーブルやクエリが存在していること、または名前が正しいことを確認してください。」と出ます
 
 Do Until rs.EOF
rs.Edit
rs!連番 = rs!連番 - 1

rs.Update
rs.MoveNext
Loop

    rs.Close
    Set rs = Nothing

    db.Close: Set db = Nothing

End Sub

ネットでコードを必死で探して作ってみたのでもしかしたら根本的な事がわかってないかもしれません
よろしくお願いします

【12929】Re:カレントレコードのサブIDが前のレコ...
発言  まるこ  - 16/1/18(月) 13:15 -

引用なし
パスワード
   間違えました

rs!連番 = rs!連番 - 1



rs!連番 = rs!連番2 - 1

でした
すみません

【12930】Re:カレントレコードのサブIDが前のレコ...
発言  まるこ  - 16/1/18(月) 13:28 -

引用なし
パスワード
   自己解決しました
テーブルAをダブルクオテーションで囲んだら出来ました
すみませんお騒がせしました

また来ると思いますのでその時はよろしくお願いします

【12936】Re:カレントレコードのサブIDが前のレコ...
お礼  まるこ  - 16/2/5(金) 13:57 -

引用なし
パスワード
   大変遅くなって申し訳ありません
めちゃめちゃ苦労しましたが何とかできました
ありがとうございました。
また、質問させていただきたいことができましたので、
何度もすみませんが、別スレッドを立てさせていただきます
よろしくお願いします

125 / 2272 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
1078188
(SS)C-BOARD v3.8 is Free