Php / mysql排名系统 - 按列排序的结果集内的放置

时间:2015-04-18 14:59:10

标签: php mysql

在类似博客的网站中,所有用户都可以“加注”新闻(=将其加入书签,将其标记为“收藏”)。 我有一个统计数据的mysql表。

table_news_stats

id_news
total_stars (int) //Total number of users who starred this news
placement (int)

placement字段非常直观:如果您按total_stars字段订购所有新闻,则会收到每条新闻placement。因此,大多数明星的新闻都是数字1,依此类推。

所以,假设我的table_news_stats中有700条记录,而且每个记录都有idtotal_stars,我怎样才能更新placement字段每个记录自动?哪个查询更快/更好?

table_news_stats内容示例:

First record (A):
1-3654-?

Second record (B):
2-2456-?

Third record (C):
3-8654-?

如果按星号计算记录: 记录的顺序是C - A - B

所以...结果将是:

First record (A):
1-3654-2

Second record (B):
2-2456-3

Third record (C):
3-8654-1

澄清:
为什么我需要placement字段呢? 这很简单......每个月的第一天,放置字段将由cronjob填充。基本上它将提供每个新闻在受欢迎程度方面的排名“快照”(就像当月初)。因此,感谢展示位置字段,我将获得以下信息:

"The 1st day of this month the 'top starred' news list was like this:  
1- News C  
2- NewsA  
3- News B "    

然后,通过查询“SELECT * FROM table_news_stats ORDER BY total_stars DESC”,我可以获得新的排名(实时)。

因此,我将获得以下信息:

"At the time the page is loaded, the 'top starred' news list is like this:  
1- News A  
2- News C  
3- News B "  

最后,通过比较两个排名,我获得了最后一条信息:

"News A has gained a position" +1
"News C has lost a position" -1
"News B has no change in position" +0

如果有更好的方法,请告诉我。

2 个答案:

答案 0 :(得分:5)

我猜你不需要update表格:

SELECT *
FROM table_news_stats
ORDER BY total_stars DESC

但如果你想知道每个人的位置,你可以:

SELECT *, IF(@idx IS NULL,@idx:= 1,@idx:= @idx+1) 
FROM table_news_stats
ORDER BY total_stars DESC

如果你还需要update之类的东西:

UPDATE table_news_stats 
SET placement = FIND_IN_SET(id_news,(SELECT GROUP_CONCAT(t.id_news) FROM (SELECT id_news
    FROM table_news_stats 
    ORDER BY total_stars DESC) t ))

SQLFiddle

答案 1 :(得分:3)

考虑以下

mysql> select * from test ;
+------+-------------+-----------+
| id   | total_stars | placement |
+------+-------------+-----------+
|    1 |           3 |         0 |
|    2 |           6 |         0 |
|    3 |           7 |         0 |
|    4 |           2 |         0 |
|    5 |           9 |         0 |
|    6 |           2 |         0 |
|    7 |           1 |         0 |
+------+-------------+-----------+

现在使用以下内容,您可以将placement更新为

update test t1 join
(
 select *,
 @rn:= if(@prev = total_stars,@rn,@rn+1) as rank ,
 @prev:= total_stars
 from test,(select @rn:=0,@prev:=0)r 
 order by total_stars desc
)t2
on t2.id = t1.id
set t1.placement = t2.rank ;


mysql> select * from test order by placement ;
+------+-------------+-----------+
| id   | total_stars | placement |
+------+-------------+-----------+
|    5 |           9 |         1 |
|    3 |           7 |         2 |
|    2 |           6 |         3 |
|    1 |           3 |         4 |
|    4 |           2 |         5 |
|    6 |           2 |         5 |
|    7 |           1 |         6 |
+------+-------------+-----------+

请注意,如果领带将具有相同的位置。