重複クエリウィザードはレコードをどのように抽出しているか

 重複クエリウィザードは、テーブルやクエリに含まれる1つの、あるいは複数の列に注目して、同じ値を持つレコードをすべて抽出するときに用います。
 値が重複する部分だけでなくほかの列の値も一緒に抽出できるので大変便利ですが、ここではそのデザインの内容から、どのようにレコードを抽出しているのかを見てみます。

f:id:accs2014:20180702003837p:plain:right:w500

 サンプルとしてこのようなテーブルを用います。


f:id:accs2014:20180702003832p:plain:right:w500

 まず最初の例ですが重複クエリウィザードを使って、出身地が重複する者、つまり他にも同じ出身地の者がいる者を抽出した結果がこちらです。


f:id:accs2014:20180702003834p:plain:right:w600

 具体的にどのような抽出を行っているかですが、デザインビューで見てみますと、出身地列の抽出条件欄に次のように記されています。


In (SELECT [出身地] FROM [会員テーブル] As Tmp GROUP BY [出身地] HAVING Count(*)>1 )

 サブクエリになっていますが別段難しいものではありません。
 SELECT文により、出身地として2回以上出現する値を抽出し、それにあてはまれば抽出し、そうでなければ抽出しない、というだけのことです。

f:id:accs2014:20180702003826p:plain:right:w500

 さて次の本題です。
 重複クエリウィザードを使って、血液型と出身地の両方が重複する者を抽出した結果がこちらです。「A型、埼玉県」が3人、「B型、千葉県」が2人、「O型、千葉県」が2人いることがわかります。


f:id:accs2014:20180702003828p:plain:right:w600

 デザインビューで見てみますと、出身地列の抽出条件欄に次のように記されています。



In (SELECT [血液型] FROM [会員テーブル] As Tmp GROUP BY [血液型],[出身地] HAVING Count(*)>1  And [出身地] = [会員テーブル].[出身地])

 ここが一見不思議なところで、「血液型と出身地の両方が重複する」という条件をつけたのに、抽出条件があるのは血液型列だけです。
 それだと特定の血液型の者がすべて(たとえばA型の者が6名すべて)抽出されるように思えるかもしれませんが、上記の結果からわかるようにそうはならず、血液型と出身地の両方が重複するレコードだけをきちんと抽出しています。
 なぜなのかを知るにはまず相関サブクエリのはたらきを理解する必要がありちょっと難しいのですが、こうなるのは、SELECT文のグループ化の対象として血液型だけでなく出身地が含まれており、さらに「HAVING Count(*)>1」の後に「 And [出身地] = [会員テーブル].[出身地]」があるからです。これにより「血液型と出身地の両方が一致するレコードが他に存在する場合のみ、サブクエリがその血液型を返す」こととなり、(一見出身地には条件がついてないように見えて)実際は血液型と出身地の両方について条件付けがされているからです。このサブクエリの結果がNullになる場合もありますが、「In (Null)」でNullを抽出することはできませんので、血液型としてNullが返される(抽出される)こともありません。結果的にこのクエリは(当たり前ですが)正しく機能します。

 ついでになりますが、「In (Null)」でNullを抽出することはできない、ということについては次の記事が参考になるかと思います。

www.accessdbstudy.net