Access VBA質問箱 IV

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

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


383 / 9994 ←次へ | 前へ→

【12924】Re:カレントレコードのサブIDが前のレコードのサブ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必須です。

186 hits

【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 お礼[未読]

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