MySQL 获取 ORDER BY 中的行位置

发布于 2024-09-16 18:32:32 字数 896 浏览 12 评论 0原文

对于以下 MySQL 表:

+-----------------------------+
+ id INT UNSIGNED             +
+ name VARCHAR(100)           +
+-----------------------------+

当按名称 ASC 排序时,如何选择行及其在表中其他行中的位置。因此,如果表数据如下所示,按名称排序时:

+-----------------------------+
+ id | name                   +
+-----------------------------+
+  5 | Alpha                  +
+  7 | Beta                   +
+  3 | Delta                  +
+ .....                       +
+  1 | Zed                    +
+-----------------------------+

我如何选择 Beta 行来获取该行的当前位置?我正在寻找的结果集将是这样的:

+-----------------------------+
+ id | position | name        +
+-----------------------------+
+  7 |        2 | Beta        +
+-----------------------------+

我可以做一个简单的 SELECT * FROM tbl ORDER BY name ASC ,然后枚举 PHP 中的行,但加载可能很大的行似乎很浪费结果集仅针对单行。

With the following MySQL table:

+-----------------------------+
+ id INT UNSIGNED             +
+ name VARCHAR(100)           +
+-----------------------------+

How can I select a single row AND its position amongst the other rows in the table, when sorted by name ASC. So if the table data looks like this, when sorted by name:

+-----------------------------+
+ id | name                   +
+-----------------------------+
+  5 | Alpha                  +
+  7 | Beta                   +
+  3 | Delta                  +
+ .....                       +
+  1 | Zed                    +
+-----------------------------+

How could I select the Beta row getting the current position of that row? The result set I'm looking for would be something like this:

+-----------------------------+
+ id | position | name        +
+-----------------------------+
+  7 |        2 | Beta        +
+-----------------------------+

I can do a simple SELECT * FROM tbl ORDER BY name ASC then enumerate the rows in PHP, but it seems wasteful to load a potentially large resultset just for a single row.

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

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

发布评论

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

评论(9

嘿哥们儿 2024-09-23 18:32:32

使用此:

SELECT x.id, 
       x.position,
       x.name
  FROM (SELECT t.id,
               t.name,
               @rownum := @rownum + 1 AS position
          FROM TABLE t
          JOIN (SELECT @rownum := 0) r
      ORDER BY t.name) x
 WHERE x.name = 'Beta'

...获得唯一的位置值。这:

SELECT t.id,
       (SELECT COUNT(*)
          FROM TABLE x
         WHERE x.name <= t.name) AS position,
       t.name    
  FROM TABLE t      
 WHERE t.name = 'Beta'

...将为关系赋予相同的值。 IE:如果第二位有两个值,那么当第一个查询将为其中一个提供 2 的位置,另一个为 3 时,它们的位置都将为 2...

Use this:

SELECT x.id, 
       x.position,
       x.name
  FROM (SELECT t.id,
               t.name,
               @rownum := @rownum + 1 AS position
          FROM TABLE t
          JOIN (SELECT @rownum := 0) r
      ORDER BY t.name) x
 WHERE x.name = 'Beta'

...to get a unique position value. This:

SELECT t.id,
       (SELECT COUNT(*)
          FROM TABLE x
         WHERE x.name <= t.name) AS position,
       t.name    
  FROM TABLE t      
 WHERE t.name = 'Beta'

...will give ties the same value. IE: If there are two values at second place, they'll both have a position of 2 when the first query will give a position of 2 to one of them, and 3 to the other...

椒妓 2024-09-23 18:32:32

这是我能想到的唯一方法:

SELECT `id`,
       (SELECT COUNT(*) FROM `table` WHERE `name` <= 'Beta') AS `position`,
       `name`
FROM `table`
WHERE `name` = 'Beta'

This is the only way that I can think of:

SELECT `id`,
       (SELECT COUNT(*) FROM `table` WHERE `name` <= 'Beta') AS `position`,
       `name`
FROM `table`
WHERE `name` = 'Beta'
孤凫 2024-09-23 18:32:32

如果查询很简单并且返回的结果集可能很大,那么您可以尝试将其拆分为两个查询。

第一个查询使用缩小过滤条件,仅检索该行的数据,第二个查询使用 COUNTWHERE 子句来计算位置。

例如,在您的情况下,

查询 1:

SELECT * FROM tbl WHERE name = 'Beta'

查询 2:

SELECT COUNT(1) FROM tbl WHERE name >= 'Beta'

我们在具有 2M 记录的表中使用此方法,这比 OMG Ponies 的方法更具可扩展性。

If the query is simple and the size of returned result set is potentially large, then you may try to split it into two queries.

The first query with a narrow-down filtering criteria just to retrieve data of that row, and the second query uses COUNT with WHERE clause to calculate the position.

For example in your case

Query 1:

SELECT * FROM tbl WHERE name = 'Beta'

Query 2:

SELECT COUNT(1) FROM tbl WHERE name >= 'Beta'

We use this approach in a table with 2M record and this is way more scalable than OMG Ponies's approach.

梦亿 2024-09-23 18:32:32

其他答案对我来说似乎太复杂了。

这里有一个简单的例子,假设你有一个包含列的表格:

userid | points

并且你想按点对用户ID进行排序并获取行位置(用户的“排名”),然后你使用:

SET @row_number = 0;

SELECT 
    (@row_number:=@row_number + 1) AS num, userid, points
FROM
    ourtable
ORDER BY points DESC

num 为您提供行位置(排名)。

如果您有 MySQL 8.0+,那么您可能需要使用 ROW_NUMBER()

The other answers seem too complicated for me.

Here comes an easy example, let's say you have a table with columns:

userid | points

and you want to sort the userids by points and get the row position (the "ranking" of the user), then you use:

SET @row_number = 0;

SELECT 
    (@row_number:=@row_number + 1) AS num, userid, points
FROM
    ourtable
ORDER BY points DESC

num gives you the row postion (ranking).

If you have MySQL 8.0+ then you might want to use ROW_NUMBER()

羁客 2024-09-23 18:32:32

表中行的位置表示有多少行比目标行“更好”。

因此,您必须计算这些行。

SELECT COUNT(*)+1 FROM table WHERE name<'Beta'

如果出现平局,则返回最高位置。

如果在现有“Beta”行之后添加另一行具有相同名称“Beta”,则返回的位置仍为 2,因为它们将在分类中共享相同的位置。

希望这对将来搜索类似内容的人有所帮助,因为我相信问题所有者已经解决了他的问题。

The position of a row in the table represents how many rows are "better" than the targeted row.

So, you must count those rows.

SELECT COUNT(*)+1 FROM table WHERE name<'Beta'

In case of a tie, the highest position is returned.

If you add another row with same name of "Beta" after the existing "Beta" row, then the position returned would be still 2, as they would share same place in the classification.

Hope this helps people that will search for something similar in the future, as I believe that the question owner already solved his issue.

小女人ら 2024-09-23 18:32:32

我有一个非常非常相似的问题,这就是为什么我不会问同样的问题,但我将在这里分享我做了什么,我还必须使用 group by 和 order by AVG。
有学生,有签名和socore,我必须对他们进行排名(换句话说,我首先计算AVG,然后在DESC中对他们进行排序,最后我需要添加位置(对我来说排名),所以我做了与此处的最佳答案非常相似,只是根据我的问题进行了一些更改):

我最后放置了位置(对我来说排名) 外部 SELECT 中的列

SET @rank=0;
SELECT @rank := @rank + 1 AS ranking, t.avg, t.name
  FROM(SELECT avg(students_signatures.score) as avg, students.name as name
FROM alumnos_materia
JOIN (SELECT @rownum := 0) r
left JOIN students ON students.id=students_signatures.id_student
GROUP BY students.name order by avg DESC) t 

I've got a very very similar issue, that's why I won't ask the same question, but I will share here what did I do, I had to use also a group by, and order by AVG.
There are students, with signatures and socore, and I had to rank them (in other words, I first calc the AVG, then order them in DESC, and then finally I needed to add the position (rank for me), So I did something Very similar as the best answer here, with a little changes that adjust to my problem):

I put finally the position (rank for me) column in the external SELECT

SET @rank=0;
SELECT @rank := @rank + 1 AS ranking, t.avg, t.name
  FROM(SELECT avg(students_signatures.score) as avg, students.name as name
FROM alumnos_materia
JOIN (SELECT @rownum := 0) r
left JOIN students ON students.id=students_signatures.id_student
GROUP BY students.name order by avg DESC) t 
许一世地老天荒 2024-09-23 18:32:32

我正在查看已接受的答案,它看起来有点复杂,所以这里是它的简化版本。

SELECT t,COUNT(*) AS position FROM t      
 WHERE name <= 'search string' ORDER BY name

I was going through the accepted answer and it seemed bit complicated so here is the simplified version of it.

SELECT t,COUNT(*) AS position FROM t      
 WHERE name <= 'search string' ORDER BY name
我爱人 2024-09-23 18:32:32

我有类似类型的问题,我需要表order by votes desc的排名(Index)。以下内容对我来说效果很好。

Select *, ROW_NUMBER() OVER(ORDER BY votes DESC) as "rank"
From "category_model"
where ("model_type" = ? and "category_id" = ?)

I have similar types of problem where I require rank(Index) of table order by votes desc. The following works fine with for me.

Select *, ROW_NUMBER() OVER(ORDER BY votes DESC) as "rank"
From "category_model"
where ("model_type" = ? and "category_id" = ?)
凉世弥音 2024-09-23 18:32:32

可能是您需要的是添加语法,

LIMIT

因此

SELECT * FROM tbl ORDER BY name ASC LIMIT 1

如果您只需要一行,请使用..

may be what you need is with add syntax

LIMIT

so use

SELECT * FROM tbl ORDER BY name ASC LIMIT 1

if you just need one row..

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