您的查询未使用 SQL-92JOIN
语法,而是使用较旧的隐式连接语法。是时候(20 年了),你应该开始使用它了。
COUNT
使用别名等关键字也不是很好。您可以使用cnt
orbook_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 JOIN
为LEFT 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)