1

次のテーブルがあります。

  1. link_books_genres , *テーブル構造 -> book_id,genre_id*
  2. ジャンル, *テーブル構造 -> ジャンル_id,ジャンル名*

book_ids のセットを指定して、次の結果を作成したいと思います。

result_set structure -> genre_id, genre_name, count(book_id).

私はこのクエリを書きました、

SELECT one.genre_id,
       one.genre_name, 
       two.count 
FROM   genres as one,(SELECT genre_id,
                   count(book_id) as count 
                   FROM link_f2_books_lists GROUP BY genre_id) as two 
WHERE  one.genre_id = two.genre_id;

それが最善の解決策かどうかはわかりませんが、可能であれば最適化するか、適切な形式で検証されているかどうかを確認してください。

PS Ruby on Railsで行われているため、レール指向のアプローチでも問題ありません。

4

2 に答える 2

2

クエリは 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)

于 2012-04-10T19:57:06.243 に答える
0
SELECT one.genre_id, one.genre_name,  count(two.book_id) 
FROM genres as one, link_books_genres as two 
WHERE one.genre_id=two.genre_id
GROUP BY genre_id
于 2012-04-10T19:59:26.187 に答える