我有一个文章表和一个类别表。我想为每个类别获取7篇文章。目前,我有这个功能,但是在大型表上速度很慢,所以这不是一个真正的解决方案:
SELECT id, title, categories_id, body, DATE_FORMAT(pubdate, "%d/%m/%y %H:%i") as pubdate FROM articles AS t WHERE ( SELECT COUNT(*) FROM articles WHERE t.categories_id = categories_id AND id< t.id AND publish = 1 AND expires > '2008-12-14 18:38:02' AND pubdate <= '2008-12-14 18:38:02' ) < 7 ORDER BY categories_id DESC
使用explain,它向我展示了它正在做一个ALL&REF联接类型。选择类型为PRIMARY和DEPENDENT子查询。
有更好的解决方案吗?
这是解决此问题的方法:
SELECT a1.id, a1.title, a1.categories_id, a1.body, DATE_FORMAT(a1.pubdate, "%d/%m/%y %H:%i") as pubdate FROM articles AS a1 LEFT OUTER JOIN articles AS a2 ON (a1.categories_id = a2.categories_id AND (a1.pubdate < a2.pubdate OR (a1.pubdate = a2.pubdate AND a1.id < a2.id))) GROUP BY a1.id HAVING COUNT(*) < 7;
相关的子查询通常性能较差,因此该技术使用联接代替。
对于给定的文章,搜索与正在考虑的当前文章的类别(a1)相匹配的文章(a2),并且其日期较新(id
如果是平局,则为更高日期)。如果满足该条件的文章少于七个,则当前文章必须是该类别中最新的文章之一。
如果您可以依赖id
具有与相同排序顺序的唯一列pubdate
,那么您可以简化连接,因为唯一列之间没有联系:
ON (a1.categories_id = a2.categories_id AND a1.id < a2.id)