使用MySQL,如何在表中生成包含记录索引的列?

时间:2010-06-27 09:37:26

标签: mysql indexing

有什么办法可以从查询中获取实际的行号吗?

我希望能够通过名为score的字段订购名为league_girl的表格;并返回该用户名的用户名和实际行位置。

我想对用户进行排名,以便我能分辨出特定用户的位置,即。乔在200中排名第100,即

User Score Row
Joe  100    1
Bob  50     2
Bill 10     3

我在这里看到了一些解决方案,但我已经尝试了大部分解决方案,但实际上并没有返回行号。

我试过这个:

SELECT position, username, score
FROM (SELECT @row := @row + 1 AS position, username, score 
       FROM league_girl GROUP BY username ORDER BY score DESC) 

衍生

...但它似乎没有返回行位置。

有什么想法吗?

8 个答案:

答案 0 :(得分:166)

您可能需要尝试以下操作:

SELECT  l.position, 
        l.username, 
        l.score,
        @curRow := @curRow + 1 AS row_number
FROM    league_girl l
JOIN    (SELECT @curRow := 0) r;

JOIN (SELECT @curRow := 0)部分允许变量初始化,而无需单独的SET命令。

测试用例:

CREATE TABLE league_girl (position int, username varchar(10), score int);
INSERT INTO league_girl VALUES (1, 'a', 10);
INSERT INTO league_girl VALUES (2, 'b', 25);
INSERT INTO league_girl VALUES (3, 'c', 75);
INSERT INTO league_girl VALUES (4, 'd', 25);
INSERT INTO league_girl VALUES (5, 'e', 55);
INSERT INTO league_girl VALUES (6, 'f', 80);
INSERT INTO league_girl VALUES (7, 'g', 15);

测试查询:

SELECT  l.position, 
        l.username, 
        l.score,
        @curRow := @curRow + 1 AS row_number
FROM    league_girl l
JOIN    (SELECT @curRow := 0) r
WHERE   l.score > 50;

结果:

+----------+----------+-------+------------+
| position | username | score | row_number |
+----------+----------+-------+------------+
|        3 | c        |    75 |          1 |
|        5 | e        |    55 |          2 |
|        6 | f        |    80 |          3 |
+----------+----------+-------+------------+
3 rows in set (0.00 sec)

答案 1 :(得分:37)

SELECT @i:=@i+1 AS iterator, t.*
FROM tablename t,(SELECT @i:=0) foo

答案 2 :(得分:7)

我使用的模板结构如下:

  select
          /*this is a row number counter*/
          ( select @rownum := @rownum + 1 from ( select @rownum := 0 ) d2 ) 
          as rownumber,
          d3.*
  from 
  ( select d1.* from table_name d1 ) d3

这是我的工作代码:

select     
           ( select @rownum := @rownum + 1 from ( select @rownum := 0 ) d2 ) 
           as rownumber,
           d3.*
from
(   select     year( d1.date ), month( d1.date ), count( d1.id )
    from       maindatabase d1
    where      ( ( d1.date >= '2013-01-01' ) and ( d1.date <= '2014-12-31' ) )
    group by   YEAR( d1.date ), MONTH( d1.date ) ) d3

答案 3 :(得分:4)

您也可以使用

SELECT @curRow := ifnull(@curRow,0) + 1 Row, ...

初始化计数器变量。

答案 4 :(得分:3)

假设MySQL支持它,您可以使用标准SQL子查询轻松完成此操作:

select 
    (count(*) from league_girl l1 where l2.score > l1.score and l1.id <> l2.id) as position,
    username,
    score
from league_girl l2
order by score;

对于大量显示的结果,这会有点慢,你会想要切换到自连接。

答案 5 :(得分:3)

如果您只想知道按字段分数排序后某个特定用户的位置,您只需从表格中选择字段分数高于当前用户分数的所有行。并使用返回的行号+ 1来知道当前用户的位置。

假设你的桌子是“league_girl”而你的主要字段是“id”,你可以使用它:

SELECT count(id) + 1 as rank from league_girl where score > <your_user_score>

答案 6 :(得分:0)

我知道OP要求mysql答案但是因为我发现其他答案对我不起作用,

  • 其中大多数都以order by
  • 失败
  • 或者他们只是非常无效并且使你的查询对于胖桌来说非常慢

为了节省像我这样的人的时间,只需在从数据库中检索行后对行进行索引

PHP中的

示例:

        $users = UserRepository::loadAllUsersAndSortByScore();

        foreach($users as $index=>&$user){
            $user['rank'] = $index+1;
        }

使用偏移和限制进行分页的PHP示例:

        $limit = 20; //page size
        $offset = 3; //page number

        $users = UserRepository::loadAllUsersAndSortByScore();

        foreach($users as $index=>&$user){
            $user['rank'] = $index+1+($limit*($offset-1));
        }

答案 7 :(得分:0)

我发现原始答案非常有用,但我也想根据要插入的行号来抓取一组特定的行。这样,我将整个原始答案包装在子查询中,以便可以引用要插入的行号。

SELECT * FROM 
( 
    SELECT *, @curRow := @curRow + 1 AS "row_number"
    FROM db.tableName, (SELECT @curRow := 0) r
) as temp
WHERE temp.row_number BETWEEN 1 and 10;

在子查询中具有子查询的效率不是很高,因此值得测试是否让SQL Server处理此查询,或者获取整个表并让应用程序/ Web服务器操纵行来获得更好的结果事实之后。

我个人的SQL Server并不是很忙,所以最好让它处理嵌套的子查询。