(旧) kano-e no memo

こっちは更新してません

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の記事、すごく参考になりました。

今日は仕事中、いっぱいSQL書いたりSQLの勉強できたりして、幸せでしたー!