MySQL получить положение строки в ORDER BY - PullRequest
76 голосов
/ 01 сентября 2010

Со следующей таблицей MySQL:

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

Как выбрать одну строку И ее положение среди других строк в таблице, если они отсортированы по name 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, но загружать потенциально большой набор результатов только для одной строки представляется расточительным.

Ответы [ 7 ]

108 голосов
/ 01 сентября 2010

Используйте это:

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, когда первый запрос даст позицию 2 для одного из них и 3 для другого ...

18 голосов
/ 01 сентября 2010

Это единственный способ, о котором я могу думать:

SELECT `id`,
       (SELECT COUNT(*) FROM `table` WHERE `name` <= 'Beta') AS `position`,
       `name`
FROM `table`
WHERE `name` = 'Beta'
8 голосов
/ 12 марта 2012

Если запрос прост и размер возвращаемого набора результатов потенциально велик, вы можете попытаться разделить его на два запроса.

Первый запрос с более узкими критериями фильтрации просто для извлечения данных из этой строки, а второй запрос использует COUNT с предложением WHERE для вычисления позиции.

Например,в вашем случае

Запрос 1:

SELECT * FROM tbl WHERE name = 'Beta'

Запрос 2:

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

Мы используем этот подход втаблица с записью 2M, и это гораздо более масштабируемо, чем подход OMG Ponies.

2 голосов
/ 04 мая 2017

У меня очень очень похожая проблема, поэтому я не буду задавать тот же вопрос, но я поделюсь здесь тем, что я сделал, мне пришлось использовать также группу по заказу AVG. Есть студенты с подписями и так же, и я должен был их ранжировать (другими словами, я сначала вычисляю AVG, затем заказываю их в DESC, и, наконец, мне нужно было добавить позицию (ранг для меня), поэтому я сделал что-то Очень похоже как лучший ответ здесь, с небольшими изменениями, которые подстраиваются под мою проблему):

Наконец, я поставил столбец position (rank for me) во внешнем 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 
1 голос
/ 14 ноября 2018

Другие ответы кажутся мне слишком сложными.

Вот простой пример . Допустим, у вас есть таблица со столбцами:

userid | points

и вы хотите отсортировать идентификаторы пользователей по точкам и получить позицию в строке («рейтинг» пользователя), затем вы используете:

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 ()

1 голос
/ 23 мая 2014

Положение строки в таблице показывает, сколько строк «лучше», чем целевая строка.

Итак, вы должны считать эти строки.

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

В случае ничьей возвращается наивысшая позиция.

Если вы добавите еще одну строку с таким же именем "Beta" послев существующей строке «бета» возвращаемая позиция по-прежнему будет равна 2, поскольку они будут занимать одно и то же место в классификации.

Надеюсь, это поможет людям, которые будут искать что-то подобное в будущем, так как я считаю, чтовладелец вопроса уже решил свою проблему.

0 голосов
/ 01 сентября 2010

может быть тем, что вам нужно, с синтаксисом добавления

LIMIT

, поэтому используйте

SELECT * FROM tbl ORDER BY name ASC LIMIT 1

, если вам нужна только одна строка ..

...