MySQL在ORDER BY中获取行位置

lee*_*ers 77 mysql sql analytic-functions

使用以下MySQL表:

+-----------------------------+
+ id INT UNSIGNED             +
+ name VARCHAR(100)           +
+-----------------------------+
Run Code Online (Sandbox Code Playgroud)

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

+-----------------------------+
+ id | name                   +
+-----------------------------+
+  5 | Alpha                  +
+  7 | Beta                   +
+  3 | Delta                  +
+ .....                       +
+  1 | Zed                    +
+-----------------------------+
Run Code Online (Sandbox Code Playgroud)

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

+-----------------------------+
+ id | position | name        +
+-----------------------------+
+  7 |        2 | Beta        +
+-----------------------------+
Run Code Online (Sandbox Code Playgroud)

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

OMG*_*ies 109

用这个:

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'
Run Code Online (Sandbox Code Playgroud)

...获得独特的位置价值.这个:

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

...将给予关系相同的价值.IE:如果第二个位置有两个值,当第一个查询的位置为2到1时,它们的位置都为2,而另一个的位置为3 ......

  • @OMGPonies忘了"位置"之后的逗号,但它很完美. (2认同)

zer*_*kms 18

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

SELECT `id`,
       (SELECT COUNT(*) FROM `table` WHERE `name` <= 'Beta') AS `position`,
       `name`
FROM `table`
WHERE `name` = 'Beta'
Run Code Online (Sandbox Code Playgroud)

  • +1 不错的技巧……但是您可能想改用`name &lt;= 'Beta'` (2认同)

小智 8

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

第一个带有缩小过滤条件的查询只是为了检索该行的数据,第二个查询使用COUNTwith WHERE子句来计算位置.

例如在你的情况下

查询1:

SELECT * FROM tbl WHERE name = 'Beta'

查询2:

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

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


Kai*_*ack 6

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

这是一个简单的示例,假设您有一个包含列的表:

userid | points
Run Code Online (Sandbox Code Playgroud)

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

SET @row_number = 0;

SELECT 
    (@row_number:=@row_number + 1) AS num, userid, points
FROM
    ourtable
ORDER BY points DESC
Run Code Online (Sandbox Code Playgroud)

num 给你行位置(排名)。

如果你有 MySQL 8.0+,那么你可能想使用ROW_NUMBER()