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 完成的,所以任何面向 rails 的方法也可以。

4

2 回答 2

2

您的查询未使用 SQL-92JOIN语法,而是使用较旧的隐式连接语法。是时候(20 年了),你应该开始使用它了。

COUNT使用别名等关键字也不是很好。您可以使用cntorbook_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 ;

在这两个版本中,您都可以按顺序更改INNER JOINLEFT OUTER JOIN不显示任何书籍(0 个)的流派。但是然后使用COUNT(two.book_id)and not COUNT(*),以获得正确的结果。

上述版本(和您的版本)将不包括这些类型(这是使用JOIN语法的一个很好的理由,所需的更改非常简单。尝试使用您的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 回答