MySQL получить позицию строки в порядке
со следующей таблицей 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, но кажется расточительным загружать потенциально большой набор результатов только для одной строки.
6 ответов:
используйте этот:
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 для другого...
Это единственный способ, который я могу придумать:
SELECT `id`, (SELECT COUNT(*) FROM `table` WHERE `name` <= 'Beta') AS `position`, `name` FROM `table` WHERE `name` = 'Beta'
если запрос прост и размер возвращаемого результирующего набора потенциально велик, то вы можете попытаться разделить его на два запроса.
первый запрос с узкими критериями фильтрации только для получения данных этой строки, а второй запрос использует
COUNT
сWHERE
предложение для вычисления позиции.например, в вашем случае
запрос 1:
SELECT * FROM tbl WHERE name = 'Beta'
запрос 2:
SELECT COUNT(1) FROM tbl WHERE name >= 'Beta'
мы используем этот подход в таблице с записью 2M, и это способ более масштабируемый, чем подход OMG Ponies.
у меня очень похожая проблема, поэтому я не буду задавать один и тот же вопрос, но я поделюсь здесь тем, что я сделал, мне пришлось использовать также группу by и заказать AVG. Есть студенты, с подписями и socore, и я должен был ранжировать их (другими словами, я сначала вычисляю AVG, затем упорядочиваю их в DESC, а затем, наконец, мне нужно было добавить позицию (ранг для меня), поэтому я сделал что-то очень похоже как лучший ответ здесь, с небольшими изменениями, которые регулируют моя проблема):
Я наконец-то
position
(ранг для меня) столбец во внешнем SELECTSET @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
позиция строки в таблице представляет, сколько строк "лучше", чем целевая строка.
Итак, вы должны считать эти строки.
ВЫБЕРИТЕ COUNT (*)+1 FROM
table
здесьname
в случае ничьей возвращается самая высокая позиция.
Если вы добавите еще одну строку с тем же именем "Beta" после существующей строки "Beta", то возвращенная позиция будет по-прежнему 2, так как они будут разделять одно и то же место в классификация.
надеюсь, что это поможет людям, которые будут искать что-то подобное в будущем, так как я считаю, что вопрос владелец уже решил свою проблему.