MySQL - получить номер строки при выборе

152

Можно ли запустить оператор select и получить номер строки, если элементы отсортированы?

У меня есть таблица вроде этого:

mysql> describe orders;
+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| orderID     | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| itemID      | bigint(20) unsigned | NO   |     | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+

Затем я могу запустить этот запрос, чтобы получить количество заказов по ID:

SELECT itemID, COUNT(*) as ordercount
FROM orders
GROUP BY itemID ORDER BY ordercount DESC;

Это дает мне счет каждого itemID в таблице следующим образом:

+--------+------------+
| itemID | ordercount |
+--------+------------+
|    388 |          3 |
|    234 |          2 |
|   3432 |          1 |
|    693 |          1 |
|   3459 |          1 |
+--------+------------+

Я хочу также получить номер строки, поэтому я мог сказать, что itemID=388 - это первая строка, 234 - вторая и т.д. (по существу, ранжирование заказов, а не только сырое количество). Я знаю, что могу сделать это на Java, когда получаю результат, но мне было интересно, есть ли способ обработать его только в SQL.

Обновление

Установка ранга добавляет его в результирующий набор, но не упорядочен правильно:

mysql> SET @rank=0;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @rank:=@rank+1 AS rank, itemID, COUNT(*) as ordercount
    -> FROM orders
    -> GROUP BY itemID ORDER BY rank DESC;
+------+--------+------------+
| rank | itemID | ordercount |
+------+--------+------------+
|    5 |   3459 |          1 |
|    4 |    234 |          2 |
|    3 |    693 |          1 |
|    2 |   3432 |          1 |
|    1 |    388 |          3 |
+------+--------+------------+
5 rows in set (0.00 sec)
  • 1
    Для дальнейшего использования: если вы хотите сделать заказ от ранга 1 до ранга 5, используйте ORDER BY rank ASC (упорядочение по рангу в порядке ASCending). Я думаю, это то, что вы имеете в виду, но не правильно упорядочены
  • 0
    Возможный дубликат ROW_NUMBER () в MySQL
Теги:
row-number

4 ответа

159
Лучший ответ

Посмотрите это.

Измените свой запрос на:

SET @rank=0;
SELECT @rank:=@rank+1 AS rank, itemID, COUNT(*) as ordercount
  FROM orders
  GROUP BY itemID
  ORDER BY ordercount DESC;
  • 1
    Это добавляет рейтинг к набору результатов, но не помещает их в правильном порядке - обновленный вопрос с результатами
  • 1
    Попробуйте сохранить ORDER BY ordercount DESC , а затем оберните весь запрос в другой SELECT который получает все от первого, но упорядочивает по столбцу ранга (в данном случае 0).
Показать ещё 6 комментариев
169
SELECT @rn:=@rn+1 AS rank, itemID, ordercount
FROM (
  SELECT itemID, COUNT(*) AS ordercount
  FROM orders
  GROUP BY itemID
  ORDER BY ordercount DESC
) t1, (SELECT @rn:=0) t2;
  • 1
    Спасибо за разъяснение, это решило проблему не по порядку, которая у меня была.
  • 1
    Спасибо, это было действительно полезно для меня :) Я удивлен, что нет более простого способа получить «индексы» строк из набора результатов ... но в любом случае, спасибо, это было удобно.
Показать ещё 3 комментария
26

Решение Swamibebop работает, но, используя синтаксис table.*, Мы можем избежать повторения имен столбцов внутреннего select и получить более простой/короткий результат:

SELECT @r := @r+1 , 
       z.* 
FROM(/* your original select statement goes in here */)z, 
(SELECT @r:=0)y;

Так что это даст вам:

SELECT @r := @r+1 , 
       z.* 
FROM(
     SELECT itemID, 
     count(*) AS ordercount
     FROM orders
     GROUP BY itemID
     ORDER BY ordercount DESC
    )z,
    (SELECT @r:=0)y;
  • 0
    Вы случайно не знаете, почему использование @r := @r + 1 в операторе выбора работает, но если оно находится в хранимой процедуре с declare r int; set r = 0; Жалуется (на r := r +1 )?
  • 0
    @Pacerier, также гарантирован ли порядок строк при втором выборе? Я знаю, что порядок строк, возвращаемых оператором select без заказа order by, нигде не гарантирован, и самый внешний выбор - именно такой, хотя он выбирается из внутреннего упорядоченного выбора, поэтому он может быть исключением. Однако, если это не так, я не могу понять, насколько это правильное решение, поскольку у него будет тот же недостаток, что и у Майка Чибу - нет гарантии, в каком порядке выбора будут проходить записи и нумероваться.
Показать ещё 1 комментарий
9

Вы можете использовать переменные MySQL для этого. Что-то вроде этого должно работать (хотя оно состоит из двух запросов).

SELECT 0 INTO @x;

SELECT itemID, 
       COUNT(*) AS ordercount, 
       (@x:=@x+1) AS rownumber 
FROM orders 
GROUP BY itemID 
ORDER BY ordercount DESC; 
  • 0
    Осторожно, это не сработает, потому что order by происходит после оценки переменной @x . Попробуйте поэкспериментировать, заказав другие столбцы. Также поэкспериментируйте с desc и asc . Вы увидите, что много раз они терпят неудачу, и единственные случаи, когда это работает, это по счастливой случайности из-за того, что порядок вашего исходного «выбора» имеет тот же порядок, что и order by . Смотрите мое решение и / или решение Swamibebop.
  • 0
    @Pacerier ты уверен в этом? Я устал с подобным запросом в другом примере (в основном выберите из столбца чисел, и нумеруйте их в соответствии с их порядком), казалось, что если я упорядочил по var / row num, когда он изменил порядок получающихся строк, но у каждого числа была одна и та же строка num. Но если я упорядочу по числовому столбцу, то ASC / DESC изменит порядок, в котором эти номера были пронумерованы (с наименьшего до наибольшего или наоборот). Таким образом, похоже, что в этом случае order by был оценен первым.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню