クエリは SQL-92 構文を使用していませんJOIN
が、古い暗黙の結合構文を使用しています。時が来ました(今から20年)、それを使い始めるべきです。
COUNT
また、エイリアスのようなキーワードを使用することもあまり良くありません。cnt
またはbook_count
代わりに使用できます:
SELECT one.genre_id,
one.genre_name,
two.cnt
FROM
genres AS one
INNER JOIN
( SELECT genre_id,
COUNT(book_id) AS cnt
FROM link_f2_books_lists
GROUP BY genre_id
) AS two
ON one.genre_id = two.genre_id ;
通常、MySQL は を使用すると少し高速COUNT(*)
になるため、book_id
できない場合はNULL
に変更COUNT(book_id)
するCOUNT(*)
とパフォーマンスがわずかに向上します。
もちろん、派生テーブルなしで Join を書き換えることができます。
SELECT one.genre_id,
one.genre_name,
COUNT(*) AS cnt
FROM
genres AS one
INNER JOIN
link_f2_books_lists AS two
ON one.genre_id = two.genre_id
GROUP BY one.genre_id ;
どちらのバージョンでも、本を表示せずに (0 カウント) 順番にジャンルをINNER JOIN
変更できます。LEFT OUTER JOIN
ただし、正しい結果を得るには、 COUNT(two.book_id)
and notを使用してください。COUNT(*)
上記のバージョン (およびあなたのバージョン) には、これらのジャンルが含まれていません (これは、JOIN
構文を使用する正当な理由の 1 つです。必要な変更は非常に簡単です。あなたのWHERE
バージョンで試してみてください!)
LEFT JOIN
バージョンは次のように書くこともできます:
SELECT one.genre_id,
one.genre_name,
( SELECT COUNT(*)
FROM link_f2_books_lists AS two
WHERE one.genre_id = two.genre_id
) AS cnt
FROM
genres AS one ;
パフォーマンスに関しては、自分自身をテストすることに勝るものはありません。それはすべて、使用するMySQLのバージョンに依存します(新しいバージョンには、実行計画を作成するためのより多くのオプションを選択できるより優れたオプティマイザーがあり、おそらく異なるバージョンを同等のものとして識別します)、テーブルのサイズ、持っているインデックス、データの分布 (さまざまなジャンルがいくつあるのか? ジャンルごとに平均して何冊の本があるのか? など)、メモリ (およびその他の MySQL) の設定、そしておそらく私が今忘れている他の多くの要因。
アドバイスは(genre_id, book_id)
、ほとんどの場合、すべてのバージョンで索引が役立つということです。
一般的なアドバイスとして、通常は多対多テーブルにa(genre_id, book_id)
とインデックスの両方を用意することをお勧めします。(book_id, genre_id)