MySQL получает позицию строки в ORDER BY
Со следующей таблицей 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, но представляется бесполезным загрузить потенциально большой набор результатов только для одной строки.
Ответы
Ответ 1
Использовать этот:
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 для другого...
Ответ 2
Это единственный способ, о котором я могу думать:
SELECT `id`,
(SELECT COUNT(*) FROM `table` WHERE `name` <= 'Beta') AS `position`,
`name`
FROM `table`
WHERE `name` = 'Beta'
Ответ 3
Если запрос прост и размер возвращаемого набора результатов потенциально большой, вы можете попытаться разбить его на два запроса.
Первый запрос с критерием фильтрации с узким вниз для получения данных этой строки, а второй запрос использует COUNT
с предложением WHERE
для вычисления позиции.
Например, в вашем случае
Запрос 1:
SELECT * FROM tbl WHERE name = 'Beta'
Запрос 2:
SELECT COUNT(1) FROM tbl WHERE name >= 'Beta'
Мы используем этот подход в таблице с записью 2M, и это более масштабируемо, чем подход OMG Ponies.
Ответ 4
У меня очень похожая проблема, поэтому я не буду задавать один и тот же вопрос, но я расскажу, что я сделал, мне пришлось использовать и группу по заказу AVG.
Есть ученики, с подписями и сокровищем, и мне приходилось оценивать их (другими словами, я сначала вычисляю AVG, а затем заказываю их в DESC, а затем, наконец, мне нужно было добавить позицию (ранг для меня), поэтому я сделал что-то очень похожее на лучший ответ здесь, с небольшими изменениями, которые приспосабливаются к моей проблеме):
Я положил, наконец, столбец position
(rank для меня) во внешнем 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
Ответ 5
Позиция строки в таблице показывает, сколько строк "лучше", чем целевая строка.
Итак, вы должны считать эти строки.
SELECT COUNT (*) + 1 FROM table
WHERE name
< Beta '
В случае привязки возвращается высшая позиция.
Если вы добавите еще одну строку с тем же именем "Бета" после существующей строки "Бета", то возвращенная позиция будет равна 2, так как они будут разделять одно и то же место в классификации.
Надеюсь, что это поможет людям, которые будут искать что-то подобное в будущем, поскольку я считаю, что владелец вопроса уже решил свою проблему.
Ответ 6
Другие ответы кажутся мне слишком сложными.
Вот простой пример, скажем, у вас есть таблица со столбцами:
userid | points
и вы хотите отсортировать идентификаторы пользователей по точкам и получить позицию строки ("рейтинг" пользователя), затем вы используете:
SET @row_number = 0;
SELECT
(@row_number:[email protected]_number + 1) AS num, userid, points
FROM
ourtable
ORDER BY points DESC
num
дает вам положение строки (рейтинг).
Если у вас MySQL 8. 0+, вы можете использовать ROW_NUMBER()
Ответ 7
Я проходил через принятый ответ, и он показался мне немного сложным, поэтому вот его упрощенная версия.
SELECT t,COUNT(*) AS position FROM t
WHERE name <= 'search string' ORDER BY name
Ответ 8
может быть то, что вам нужно, с добавлением синтаксиса
LIMIT
так что пользуйтесь
SELECT * FROM tbl ORDER BY name ASC LIMIT 1
если вам просто нужен один ряд..