どもです。割と多用するのに忘れがちなので備忘録。
結論から言うと “ HAVING COUNT(条件 OR NULL) ” または 相関サブクエリと“ EXISTS ”系関数 を用いる。
例えばこういったテーブルで。
| tableA | |
|---|---|
| id | value |
| A | 1 |
| A | 2 |
| A | 3 |
| B | 1 |
| B | 2 |
SELECT * FROM tableA AS A GROUP BY A.idvalueをそれぞれOR検索、AND検索、NOT検索して結果を取り出したい場合は?
OR検索
これは単純に実現できる。
WHERE value IN (1,2)でもSELECTの結果に検索対象外カラムの情報が欲しい場合は、ANDやNOTと同様にHAVINGを使う。
HAVING COUNT(value IN (1,2) OR NULL) > 0または、相関サブクエリとEXISTSを用いる。
WHERE EXISTS ( SELECT 1 FROM tableA AS AA WHERE AA.id = A.id AND AA.value IN (1,2) )速度は [単純にWHERE](5) > [HAVING](7) くらい差がある。
[EXISTS] は対象データの状態に大きく左右されて、(1~10)くらいバラついた。
AND検索
WHEREでなくHAVINGを使う。※COUNT(X OR NULL)は条件を満たす場合のみ計上する
HAVING COUNT(value IN (1,2) OR NULL) = 2または、相関サブクエリを使う。
WHERE ( SELECT COUNT(DISTINCT value) FROM tableA AS AA WHERE AA.id = A.id AND AA.value IN (1,2) ) = 2速度は [相関サブクエリ](6) > [HAVING](7) 。サブクエリの方が微早。
NOT検索
WHEREでなくHAVINGを使う。
HAVING COUNT(value IN (1,2) OR NULL) = 0または、相関サブクエリとNOT EXISTSを用いる。
WHERE NOT EXISTS ( SELECT 1 FROM tableA AS AA WHERE AA.id = A.id AND AA.value IN (1,2) )速度は [NOT EXISTS](1~5) > [HAVING](7) 。
NOT EXISTS の速度も EXISTS 同様、検索対象の状態に大きく依存したが、計測した限りでは最大速度が EXISTS より速い結果になった。
値が動的になったりJOINしてSQLが複雑化したりても、基本形や特徴は同じ。
インデックスが正しく貼れていれば、基本的には相関サブクエリ使用の方がやや早い。ただし検索内容によって結果が早くも遅くもブレるので、自分はHAVINGの方が好き。