ранжирование записей в таблице MySQL - PullRequest
5 голосов
/ 03 февраля 2010

У меня есть таблица MySQL со многими строками. В таблице есть столбец популярности. Если я сортирую по популярности, я могу получить ранг каждого элемента. Можно ли получить ранг определенного элемента без сортировки всей таблицы? Я так не думаю. Это правильно?

Альтернативой может быть создание нового столбца для сохранения ранга, сортировка всей таблицы, а затем цикл по всем строкам и обновление рейтинга. Это крайне неэффективно. Есть ли способ сделать это в одном запросе?

Ответы [ 5 ]

9 голосов
/ 03 февраля 2010

Нет способа вычислить порядок (то, что вы называете рангом) чего-либо без предварительной сортировки таблицы или сохранения ранга.

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

Выбрать все, включая ранг

SET @rank := 0;
SELECT t.*, @rank := @rank + 1
FROM table t
ORDER BY t.popularity;

Чтобы получить элемент с определенным идентификатором, вы можете просто использовать подзапрос следующим образом:

Выберите один, включая ранг

SET @rank := 0;
SELECT * FROM (
  SELECT t.*, @rank := @rank + 1
  FROM table t
  ORDER BY t.popularity
) t2
WHERE t2.id = 1;
0 голосов
/ 13 августа 2015

Если вы делаете это с помощью PDO, вам нужно изменить запрос, чтобы все находились в пределах одного оператора, чтобы он работал правильно. См. PHP / PDO / MySQL: преобразование нескольких запросов в один запрос

Так что ответ hobodave становится примерно таким:

SELECT t.*, (@count := @count + 1) as rank
FROM table t 
CROSS JOIN (SELECT @count := 0) CONST
ORDER BY t.popularity;
0 голосов
/ 04 февраля 2010

Если вы используете таблицу InnoDb, то вы можете рассмотреть возможность создания кластеризованного индекса по столбцу популярности. (только если заказ по популярности является частым запросом). Решение также зависит от того, насколько разнообразна колонка популярности (0 - 3 не очень хорошо).

Вы можете посмотреть эту информацию о кластерном индексе, чтобы увидеть, работает ли это для вашего случая: http://msdn.microsoft.com/en-us/library/ms190639.aspx

Это относится к SQL-серверу, но концепция та же самая, также посмотрите документацию по mysql.

0 голосов
/ 03 февраля 2010

Решение Hobodave очень хорошее. В качестве альтернативы, вы можете добавить отдельный столбец ранга, а затем, когда популярность строки будет UPDATE d, запросить, чтобы определить, изменило ли это обновление популярности свой рейтинг относительно строки выше и ниже, затем UPDATE затронутые 3 строки. Вам нужно будет профилировать, чтобы увидеть, какой метод является более эффективным.

0 голосов
/ 03 февраля 2010

Вы правы, что второй подход неэффективен, если столбец ранга обновляется при каждом чтении таблицы.Однако, в зависимости от того, сколько обновлений в базе данных, вы можете рассчитать рейтинг для каждого обновления и сохранить это - это форма кэширования.Затем вы превращаете вычисляемое поле в поле с фиксированным значением.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...