Установка рейтинга на основе запроса - PullRequest
1 голос
/ 20 октября 2019

У меня есть таблица items, в которой перечислены различные элементы со столбцами id, popularity и rank.

popularity содержит int, позволяющий сортировать элементы по популярности.

Я сделал запрос на сортировку по популярности и установил ранг для каждой записи:

SELECT id,
       @curRank := @curRank + 1 AS rank
FROM items, (SELECT @curRank := 0) r
ORDER BY popularity DESC

Этот запрос отлично работает и дает результат с id и rankгде значение rank соответствует ожидаемому, и соблюдайте порядок на popularity.

. Я пытаюсь добиться установки значения rank для каждой записи, и я попытался сделать это следующим образом:

UPDATE items A
JOIN (
       SELECT id,
              @curRank := @curRank + 1 AS rank 
       FROM items, 
              (SELECT @curRank := 0) r 
       ORDER BY popularity DESC
      ) AS ranks
SET A.rank = ranks.rank 
WHERE A.id = ranks.id

Значение rank устанавливается для каждой строки, но не соответствует ORDER BY popularity DESC. Вместо этого значение ранга устанавливается в порядке id (id 1 имеет rank 1, id 2 имеет rank 2 и т. Д.).

Что я делаю неправильно?

С уважением,

Ответы [ 2 ]

3 голосов
/ 20 октября 2019

Я думаю, вы делаете это сложнее, чем должно быть.

SET @curRank = 0;

UPDATE items
SET rank = (@curRank := @curRank+1)
ORDER BY popularity DESC;

Я просто установил переменную @curRank в операторе SET перед UPDATE. Когда вы пытаетесь объединить их, это просто заставляет читателей вашего кода задуматься, что это значит.

Вам не нужно делать их частью одного и того же утверждения. Переменная сеанса будет сохранять свое значение до тех пор, пока вы выполняете оба оператора в одном сеансе базы данных.

Нет необходимости в подзапросах или объединениях. Просто используйте UPDATE ... ORDER BY (хотя UPDATE с ORDER BY не работает в MySQL, если вам нужно выполнить JOIN).

1 голос
/ 20 октября 2019

MySQL имеет удивительное поведение при работе с переменными и упорядочением.

Одна вещь, которую вы могли бы попробовать , - это порядок ранее, перемещая ORDER BY на items в подзапрос следующим образом:

UPDATE items A
JOIN (
       SELECT id,
              @curRank := @curRank + 1 AS rank 
       FROM 
            (SELECT id FROM items ORDER BY popularity DESC) items,
            (SELECT @curRank := 0) r 
      ) AS ranks
SET A.rank = ranks.rank 
WHERE A.id = ranks.id

Демонстрация на DB Fiddle :

Данные:

| id  | popularity | rank |
| --- | ---------- | ---- |
| 1   | 1          | 1    |
| 2   | 2          | 2    |
| 3   | 3          | 3    |
| 4   | 4          | 4    |
| 5   | 5          | 5    |

После обновления:

| id  | popularity | rank |
| --- | ---------- | ---- |
| 1   | 1          | 5    |
| 2   | 2          | 4    |
| 3   | 3          | 3    |
| 4   | 4          | 2    |
| 5   | 5          | 1    |
...