グループごとにn行ずつレコードを抽出する

f:id:accs2014:20171013000634p:plain:right:w300

 TOP句を使えばテーブル(クエリ)の先頭から指定した行数だけレコードを抽出できますが、それを「グループごとに何行ずつ」と指定する方法についてです。
 ただ、以下の方法では値に重複がある厳密にn件とならない場合があり、この点はDCount関数で順位をつけて絞り込む方法と変わりません。むしろそちらの方が応用もききやすく扱いやすいかと思われます。あしからず。

 例としてこのようなテーブルを用いて、グループごとに2行ずつのレコードを抽出してみます。


f:id:accs2014:20171013000630p:plain:right:w400

 デザインビューです。
 「氏名」列の抽出条件に次のように記入します。



In (SELECT TOP 2 氏名 FROM 会員テーブル AS 会員テーブル_1 WHERE 会員テーブル_1.グループ=会員テーブル.グループ)

 サブクエリでグループごとに氏名列から2行ずつ抽出し、氏名の値がそれに一致するレコードを抽出しているというわけです。ただし、TOP句により抽出されるレコードは2行ずつであるものの、氏名の重複があるとメインクエリで(つまり全体の実行結果として)1グループから3行以上のレコードが抽出される場合があります。同様の理由で、同じようなサブクエリを「グループ」列に設けると全レコード抽出されてしまいますので注意してください。
 なお、サブクエリ内にORDER BY句を置いてませんので、サブクエリ内でどの氏名が抽出されるか、結果的にどのレコードが抽出されるかは確実ではありません。


f:id:accs2014:20171013000626p:plain:right:w300

 データシートビューです。
 順番は変わってしまってますが、確かにグループごとに2行ずつ抽出されています。


f:id:accs2014:20171013000701p:plain:right:w400

 別の例として、このようなテーブルにおいてグループごとに身長の高い2人ずつのレコードを抽出してみます。


f:id:accs2014:20171013000657p:plain:right:w400

 デザインビューです。
 「身長」列の抽出条件に次のように記入します。



In (SELECT TOP 2 身長 FROM 会員テーブル AS 会員テーブル_1 WHERE 会員テーブル_1.グループ=会員テーブル.グループ ORDER BY 身長 DESC)

 最初の例と違い、ORDER BY句を置くことで(グループごとに)身長順に並べ、最初の2行ずつを抽出しています。


f:id:accs2014:20171013000654p:plain:right:w400

 データシートビューです。
 ORDER BY句を置いているので確実に同じレコードが抽出されます。