SQLで "列col1,col2,col3のいずれか1つにでも合致する" という条件で検索する場合、
SELECT * FROM tbl
WHERE ? = col1 OR ? col2 OR ? = col3
というSQLを書いていた。同じ値を指定するプレースホルダが3つもあって、大した条件でもない割に長い。
もっと短く次のように書けるということを最近知った。
SELECT * FROM tbl
WHERE ? IN (col1, col2, col3)
また、いくつかの値をセットにしてIN句を作ることもできる。下記の例では "col1とcol2が(1,3)または(2,4)" という条件である。
SELECT * FROM tbl
WHERE (col1, col2) IN ((1, 3), (2, 4))
上記のSQLではINの後の括弧内に値を記述しているが、次のようにサブクエリを書くこともできる。
SELECT * FROM tbl
WHERE (col1, col2) IN (
SELECT subCol1, subCol2
FROM subTable
WHERE id > 10)
カラムid1, status1, id2, status2, id3, status3 を持つテーブルで (id1, status1)、(id2, status2)、(id3, status3) という3つの組み合わせのうちどれか1つでも ('ab012', '3') と一致するという条件で検索する場合は次のようになる。
SELECT * FROM tbl
WHERE ('ab012', '3') IN (
(id1, status1), (id2, status2), (id3, status3))
前の例と同じテーブルで、今度は前記の3つの組み合わせがいずれも('ab012', '3')と一致しないという条件では次のようになる。NULLの場合を考慮して COALESCE を使う。
SELECT * FROM tbl
WHERE ('ab012', '3') NOT IN (
(COALESCE(id1, ''), COALESCE(status1, ''))
, (COALESCE(id2, ''), COALESCE(status2, ''))
, (COALESCE(id3, ''), COALESCE(status3, '')))
2014/02/12追記:
この記事で書いた列と列の比較を複数列に一般化したものを「行式」という。SQL-92で標準化された機能である。IN以外の比較演算子にも拡張できる(実装されているかどうか別である)。
行式はOracleとDB2で実装されているそうだ。PostgreSQLでも使える。MySQLは不明。
参考文献:WEB+DB PRESS Vol.66 SQL救急救命室 第5回
参考サイト:
PostgreSQL IN句での複数条件指定 | Fusic Developers' Weblog
Recent Comments