混合不同类别的结果,按MySQL中的分数排序

时间:2011-06-05 18:04:38

标签: php mysql sql-order-by categories

在我的PHP应用程序中,我有一个文章的mysql表,其中包含以下列:

article_id    articletext    category_id    score

每篇文章都有一个分数,根据它的受欢迎程度计算,属于特定类别(大约有10个类别)

我的问题是:如何在按类别交替时执行返回得分最高的文章的查询,以便在可能的情况下,不会连续返回相同类别的文章。 例如,如果得分最高的文章得分为100,则返回的集合将类似于:

article_id    articletext    category_id    score
-----------------------------------------------------
142           <.....>        5              100
153           <.....>        3              97
119           <.....>        5              99
169           <.....>        2              93
121           <.....>        7              89
197           <.....>        2              92
.
.
.

第一个(天真的)解决方案是执行10个选择(每个类别1个),按分数降序排序,然后,在PHP级别,在每个返回的数据集之间交替,一次选择一个结果,将它们组合在一个新阵列中。

有没有更有效的方法来实现这一目标?如果可能的话,在MySQL级别

3 个答案:

答案 0 :(得分:1)

进入前20名。如果他们不满足要求,请执行其他查询以获取缺失的部分。您应该能够在查询数量和每个返回的行数之间找到一些平衡。

我获得了前100名,它可能在90%的时间内满足要求,并且比10次单独查询更便宜,更快。

如果是SQL Server,我可以提供更多帮助......

实际上,我有另一个想法。每5分钟运行一个进程,计算列表并将其缓存在表中。对相关表进行DML使缓存无效,因此在重新填充之前不会使用它(可能是文章被删除)。如果缓存无效,您可以回过头来计算它......并且可以使用它来重新填充缓存。

可能有策略地更新缓存列表而不是重新计算它。但这可能是一个真正的挑战。

这应该有助于查询速度和减少数据库的负载。如果您的文章列表已过时5分钟,则无关紧要。哎呀,即使1分钟也行不通。

答案 1 :(得分:1)

仅用于学习目的。我做了3个类别的测试。我不知道这个查询如何在大型记录集上运行。

select * from (
(select @r:=@r+1 as rownum,article_id,articletext,category_id,score
from articles,(select @r:=0) as r
where category_id = 1
order by score desc limit 100000000) 
union all
(select @r1:=@r1+1,article_id,articletext,category_id,score
from articles,(select @r1:=0) as r
where category_id = 2
order by score desc limit 100000000)
union all
(select @r2:=@r2+1,article_id,articletext,category_id,score
from articles,(select @r2:=0) as r
where category_id = 3
order by score desc limit 100000000)
) as t
order by rownum,score desc

答案 2 :(得分:0)

你天真的解决方案正是我要做的。