JOINとWHERE
例えば、以下のようなテーブル。
- A
- id
- etc.
- B
- id
- A_id
- number
- created_at
- C
- id
- A_id
- created_at
欲しいのは、BとCの両方に存在するA_idの数。
その時、「B.numberが12で、B.created_atは2007-05-07よりも最近のもの」「C.created_atは2007-05-11より新しいもの」という条件もある。
で、とりあえず書いたのが下の。
SELECT count(DISTINCT A.id) FROM A INNER JOIN B ON A.id = B.A_id INNER JOIN C ON C.id = C.B_id WHERE B.number = 12 AND B.created_at >= '2007-05-07 00:00:00' AND C.created_at >= '2007-05-11 00:00:00'
これだと、件数が増えると時間がかかってどうも駄目っぽい。
で、色々悩んだ末、以下のような感じに。
SELECT count(A.id) FROM A INNER JOIN ( SELECT DISTINCT A_id FROM B WHERE number = 171 AND created_at >= '2007-05-07 00:00:00' ) AS BB ON A.id = BB.A_id INNER JOIN ( SELECT DISTINCT A_id FROM C WHERE created_at >= '2007-05-11 00:00:00' ) AS CC ON A.id = CC.A_id
試してみたら、上のが「1 row in set (19.55 sec)」だったのに対して、下は「1 row in set (2.18 sec)」でした。
10倍って言ったら言い過ぎ?
でも、速くなった!
手数が増えるから、遅くなるようなイメージがあったんだけど、実際は逆なのね。
よく考えたら、あらかじめ絞り込んでから付き合わせた方が速いのは、確かにその通りか。
WEB+DB PRESS Vol.38の記事、すごく参考になりました。