SELECT:複数行に対してAND条件を指定

最終更新日時:2012-11-27 16:11:58
MySQL PostgreSQL

概要


SELECT は、1行ごとにそれぞれの値を条件として指定することにより、該当行を絞り込んで検索結果として出力するので、複数行に対しての検索を行う時には特別な指定が必要です。
通常、そのような時には用途によっていわゆる集約関数を使うことにより、たいていのことは実現できるのですが、タイトルにあるような「複数行に対してAND条件を指定」は、わりとありがちな条件であるにも関わらず、スマートな方法がありません。
※あれば教えて欲しいです(^_^;

ちなみに、「複数行に対してOR条件を指定」であれば、通常は IN で対応可能です。
"=" ではなく、"<", ">" 等での OR 条件だと話は変わってきますが。

なお、元ネタはこちらのページにあったものです。
http://typea.info/tips/wiki.cgi?page=SQL+%CA%A3%BF%F4%B9%D4%A4%CB%C2%D0%A4%B7%A4%C6%A1%A2AND%BE%F2%B7%EF%A4%F2%BB%D8%C4%EA


例題


以下のようなテーブル test01 があった時、、

  f1 | f2 
 ----+----
  01 | A  
  01 | B  
  01 | C  
  02 | A  
  02 | B  
  03 | A  


f2 が "A" と "B" の両方を含む f1 を検索する SELECT 文を考えます。


重複レコードがない場合


test01 のレコードのうち、 f1, f2 のセットで重複しているものが無い(UNIQUE(f1,f2)が保証されている)のであれば、以下で実現できます。

 SELECT f1 FROM test01 WHERE f2 IN ('A','B') GROUP BY f1 HAVING count(*) >= 2;


今回は "A" と "B" の2種類の条件ですが、これがさらに増えた場合でも IN の条件を増やし、最後の count の個数を増やせば良いだけなので、AND 条件が可変となっても対応しやすいかと思います。

重複レコードがある場合


こうなると力技しか思いつきません(^_^;

 SELECT t1.f1 FROM 
  (SELECT distinct(f1) from test01 WHERE f2 = 'A') t1,
  (SELECT distinct(f1) from test01 WHERE f2 = 'B') t2
 WHERE t1.f1 = t2.f1


こちらは AND 条件が可変となった場合には、複問い合わせをその個数分だけ増やし、さらに WHERE 句の t1.f1 = t2.f1 の部分も個数分追加する必要があります。

集合演算子 INTERSECT を使っても同じように実現できます(まだこちらの方が美しい?)が、ほぼ同様なので省略します。

お問い合わせは 掲示板 にて。