mysql表中的条目排名

发布于 2024-08-20 07:49:16 字数 178 浏览 7 评论 0原文

我有一个包含很多行的 MySQL 表。该表有一个受欢迎度列。如果我按受欢迎程度排序,我可以获得每个项目的排名。是否可以在不对整个表进行排序的情况下检索特定项目的排名?我不这么认为。这是正确的吗?

另一种方法是创建一个新列来存储排名,对整个表进行排序,然后循环所有行并更新排名。这是极其低效的。有没有办法在单个查询中做到这一点?

I have a MySQL table with many rows. The table has a popularity column. If I sort by popularity, I can get the rank of each item. Is it possible to retrieve the rank of a particular item without sorting the entire table? I don't think so. Is that correct?

An alternative would be to create a new column for storing rank, sort the entire table, and then loop through all the rows and update the rank. That is extremely inefficient. Is there perhaps a way to do this in a single query?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

爱殇璃 2024-08-27 07:49:16

如果不首先对表进行排序或存储排名,则无法计算某些内容的顺序(即所谓的排名)。

但是,如果您的表已正确索引(流行度索引),那么数据库对其进行排序就很容易获得排名。我建议如下:

全选,包括排名

SET @rank := 0;
SELECT t.*, @rank := @rank + 1
FROM table t
ORDER BY t.popularity;

要获取具有特定“id”的项目,那么您可以简单地使用子查询,如下所示:

选择一个,包括排名

SET @rank := 0;
SELECT * FROM (
  SELECT t.*, @rank := @rank + 1
  FROM table t
  ORDER BY t.popularity
) t2
WHERE t2.id = 1;

There is no way to calculate the order (what you call rank) of something without first sorting the table or storing the rank.

If your table is properly indexed however (index on popularity) it is trivial for the database to sort this so you can get your rank. I'd suggest something like the following:

Select all, including rank

SET @rank := 0;
SELECT t.*, @rank := @rank + 1
FROM table t
ORDER BY t.popularity;

To fetch an item with a specific "id" then you can simply use a subquery as follows:

Select one, including rank

SET @rank := 0;
SELECT * FROM (
  SELECT t.*, @rank := @rank + 1
  FROM table t
  ORDER BY t.popularity
) t2
WHERE t2.id = 1;
私藏温柔 2024-08-27 07:49:16

如果在每次读取表时更新排名列,那么第二种方法效率低下,这是正确的。但是,根据数据库的更新数量,您可以计算每个更新的排名,并将其存储 - 这是一种缓存形式。然后,您将计算字段转换为固定值字段。

该视频介绍了 mysql 中的缓存,尽管它是特定于 Rails 的,并且一种略有不同的缓存形式,是一种非常相似的缓存策略。

You are right that the second approach is inefficent, if the rank column is updated on every table read. However, depending on how many updates there are to the database, you could calculate the rank on every update, and store that - it is a form of caching. You are then turning a calculated field into a fixed value field.

This video covers caching in mysql, and although it is rails specific, and is a slightly different form of caching, is a very similar caching strategy.

如痴如狂 2024-08-27 07:49:16

如果您使用的是 InnoDb 表,那么您可以考虑在流行度列上构建聚集索引。 (仅当流行度排序是频繁查询时)。该决定还取决于受欢迎程度列的变化程度(0 - 3 不太好)。

您可以查看聚集索引上的此信息,看看这是否适合您的情况: http://msdn.microsoft.com/en-us/library/ms190639.aspx

这是指SQL Server,但概念是相同的,也可以查找有关此的mysql文档。

If you are using an InnoDb table then you may consider building a clustered index on the popularity column. (only if the order by on popularity is a frequent query). The decision also depends on how varied the popularity column is (0 - 3 not so good).

You can look at this info on clustered index to see if this works for your case: http://msdn.microsoft.com/en-us/library/ms190639.aspx

This refers to SQL server but the concept is the same, also look up mysql documentation on this.

爱的十字路口 2024-08-27 07:49:16

如果您使用 PDO 执行此操作,则需要将查询修改为全部位于单个语句内,以便使其正常工作。请参阅 PHP/PDO/MySQL:将多个查询转换为单个查询< /a>

所以 hobodave 的答案变成了这样:

SELECT t.*, (@count := @count + 1) as rank
FROM table t 
CROSS JOIN (SELECT @count := 0) CONST
ORDER BY t.popularity;

If you're doing this using PDO then you need to modify the query to all be within the single statement in order to get it to work properly. See PHP/PDO/MySQL: Convert Multiple Queries Into Single Query

So hobodave's answer becomes something like:

SELECT t.*, (@count := @count + 1) as rank
FROM table t 
CROSS JOIN (SELECT @count := 0) CONST
ORDER BY t.popularity;
眼眸 2024-08-27 07:49:16

hobodave的解决方案非常好。或者,您可以添加一个单独的排名列,然后,每当行的受欢迎程度发生更新时,查询以确定该受欢迎程度更新是否更改了相对于其上方和下方的行的排名,然后 更新受影响的 3 行。您必须进行分析才能确定哪种方法更有效。

hobodave's solution is very good. Alternatively, you could add a separate rank column and then, whenever a row's popularity is UPDATEd, query to determine whether that popularity update changed its ranking relative to the row above and below it, then UPDATE the 3 rows affected. You'd have to profile to see which method is more efficient.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文