|
アクセスでは、あるレコードの値が他のレコードの値によって決まる
というような計算結果を表示するのは、苦手です。
今回の場合、前のレコードの値によって区分フィールドの値が決まるわけであり、アクセスが苦手とするパターンのものにほかなりません。
今回の場合、あるレコードについて、その「前のレコード」を取得できれば、
御希望のことができます。
では、どうやって「前のレコード」を取得するかです。
リレーショナルデータベースでは、テーブルにはレコードの並び順の情報を
持ちません。
したがって、あるレコードを基準として「一つ前のレコード」とか、
「二つ後のレコード」とかということでは、レコードを特定できません。
リレーショナルデータベースでは、レコードの特定は主キーによってなされます。
したがって、今回の場合、「前のレコード」の主キーの値を
計算によって求められれば、希望のことができるということになります。
主キーの値が連番であるということが保証されているのであれば、簡単です。
あるレコードについて、その「前のレコード」の主キーの値は、
あるレコードの主キーの値から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必須です。
|
|