С MySQL, как я могу создать столбец, содержащий индекс записи в таблице? - PullRequest
99 голосов
/ 27 июня 2010

Можно ли как-нибудь получить фактический номер строки из запроса?

Я хочу иметь возможность упорядочить таблицу с именем league_girl по полю с именем Score;и вернуть имя пользователя и фактическую позицию строки этого имени пользователя.

Я хочу ранжировать пользователей, чтобы я мог сказать, где находится конкретный пользователь, т.е.Джо занимает позицию 100 из 200, то есть

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 ]

167 голосов
/ 27 июня 2010

Вы можете попробовать следующее:

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)
37 голосов
/ 12 августа 2010
SELECT @i:=@i+1 AS iterator, t.*
FROM tablename t,(SELECT @i:=0) foo
7 голосов
/ 13 декабря 2014

Вот структура используемого мной шаблона:

  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
4 голосов
/ 21 августа 2013

Вы также можете использовать

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

для инициализации переменной счетчика.

3 голосов
/ 08 октября 2013

Если вы просто хотите узнать положение одного конкретного пользователя после упорядочения по баллам поля, вы можете просто выбрать все строки в вашей таблице, где оценка поля выше, чем оценка текущего пользователя.И используйте номер строки, возвращаемый + 1, чтобы узнать, какая позиция этого текущего пользователя.

Предполагая, что ваша таблица "league_girl" и ваше основное поле "id", вы можете использовать это:

SELECT count(id) + 1 as rank from league_girl where score > <your_user_score>
3 голосов
/ 23 марта 2012

Предполагая, что 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;

Для большого количества отображаемых результатов это будет немного медленным, и вы захотите переключиться на самоприсоединяйтесь вместо этого.

0 голосов
/ 22 октября 2018

Мне показалось, что оригинальный ответ невероятно полезен, но я также хотел получить определенный набор строк на основе номеров строк, которые я вставлял.Таким образом, я завернул весь исходный ответ в подзапрос, чтобы иметь возможность ссылаться на номер строки, который вставлял.

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-сервер обрабатывает этот запрос, или извлекает всю таблицу, а сервер приложений / веб-сервер манипулирует строками после факта.

Лично мой SQL-сервер не слишком занят,так что иметь дело с вложенными подзапросами было бы предпочтительнее.

0 голосов
/ 16 февраля 2016

Я знаю, что ОП запрашивает ответ 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));
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...