2016-01-07 6 views
2

У меня есть таблица под названием «победители» с идентификаторами столбцов, «категория», «оценка», «ранг».Обновить таблицу MySQL с ранжированием записей внутри групп

Мне нужно обновить таблицу и присвоить ранг в подкатегориях (category_id), которые по образцу равны 2, но могут быть больше, чем в будущем.

Большинство анонсов, которые я нашел, основаны на операторах выбора, которые просто просто выводят представление таблицы, но я нашел очень хороший ответ «Обновить» (https://stackoverflow.com/a/2727239/4560380), в частности, обновление ответа, в котором необходимы связи для совместного использования ранг.

Образец

CREATE TABLE winners (
id int, 
category_id int, 
score double, 
rank int 
); 

INSERT INTO winners VALUES 
(1, 1, 4.36, NULL), 
(2, 1, 2.35, NULL), 
(3, 1, 1.25, NULL), 
(4, 2, 4.21, NULL), 
(5, 2, 3.33, NULL), 
(6, 1, 4.24, NULL), 
(7, 1, 1.22, NULL), 
(8, 1, 1.25, NULL), 
(9, 2, 4.21, NULL), 
(10, 2, 3.63, NULL); 

+----------+-------------+-------+------+ 
|  id | category_id | score | rank | 
+----------+-------------+-------+------+ 
|  1 |   1 | 4.36 |  | 
|  2 |   1 | 2.35 |  | 
|  3 |   1 | 1.25 |  | 
|  4 |   2 | 4.21 |  | 
|  5 |   2 | 3.33 |  | 
|  6 |   1 | 4.24 |  | 
|  7 |   1 | 1.22 |  | 
|  8 |   1 | 1.25 |  | 
|  9 |   2 | 4.21 |  | 
|  10 |   2 | 3.63 |  | 
+----------+-------------+-------+------+ 

Связанный ответ выше отлично работает для данных, когда есть только одна категория беспокоиться о, но не тогда, когда есть несколько категорий или подгруппы в ранг в.

Я попытался добавить в ИНЕКЕ код (строка 8)

1. UPDATE winners 
2. JOIN  (SELECT w.score, 
3.    IF(@lastPoint <> w.score, 
4.     @curRank := @curRank + 1, 
5.     @curRank) AS rank, 
6.    @lastPoint := w.rating 
7.  FROM  winners w 
8.  WHERE category_id = 1 
9.  JOIN  (SELECT @curRank := 0, @lastPoint := 0) r 
10.  ORDER BY w.score DESC 
11. ) ranks ON (ranks.score = winners.score) 
12. SET winners.rank = ranks.rank; 

с целью попытки запуска кода дважды для каждого CATEGORY_ID но сценарий не выполняется.

Любые варианты изменения ответа выше для нескольких категорий были бы фантастическими.

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

+----------+-------------+-------+------+ 
|  id | category_id | score | rank | 
+----------+-------------+-------+------+ 
|  1 |   1 | 4.36 | 1 | 
|  6 |   1 | 4.24 | 2 | 
|  2 |   1 | 2.35 | 3 | 
|  8 |   1 | 1.25 | 4 | 
|  3 |   1 | 1.25 | 4 | 
|  7 |   1 | 1.22 | 5 | 
|  4 |   2 | 4.21 | 1 | 
|  9 |   2 | 4.21 | 1 | 
|  10 |   2 | 3.63 | 2 | 
|  5 |   2 | 3.33 | 3 | 
+----------+-------------+-------+------+ 

Спасибо, ребята!

UPDATE

удалось найти еще немного кода https://stackoverflow.com/a/13270603/4560380, что я как-то пропустил первоначально и был в состоянии modifiy его где положение для каждого CATEGORY_ID успешно. Не идеальный способ сделать это - работает несколько раз для нескольких категорий, но на данный момент это нормально. далее

set @currentRank = 0, 
@lastRating = null, 
@rowNumber = 1; 
update winners r 
inner join (
    select 
     score, 
     @currentRank := if(@lastRating = score, @currentRank, @rowNumber) rank, 
     @rowNumber := @rowNumber + if(@lastRating = score, 0, 1) rowNumber, 
     @lastRating := score 
    from winners 
    where category_id = 1 
    order by score desc 
) var on var.score = r.score 
set r.rank = var.rank 

ответы на более «автоматической» обработки нескольких категорий в рейтинге в 1 сценарий запуска по-прежнему очень приветствуется и ценится.

Благодаря

UPDATE

Просто заметил, что ответ, который я нашел не иметь дело с нулевыми баллами (0.00) очень хорошо, и помещаю их местом в середине других баллов.

shawnt00 ответ ниже работает и оценивает нулевые оценки правильно. https://stackoverflow.com/a/34667112/4560380

ответ

0
update winners 
set rank = (
    select count(score) + 1 
    from winners w2 
    where w2.category_id = winners.category_id and w2.score > winners.score 
) 

count(*) будет оценивать к нулю, даже если ни одна строка не соответствует условию, то есть верхней рейтинга. Если вы хотите густой ранга вы могли бы сделать это:

update winners 
set rank = (
    select count(distinct score) + 1 
    from winners w2 
    where w2.category_id = winners.category_id and w2.score > winners.score 
) 

EDIT: На Вашем комментарии Я нашел запрос, который делает работу.(Он работает на SQL Server, и я не знаком с причудами MySQL,.) http://sqlfiddle.com/#!9/1159f/1

update winners 
inner join (
    select w.id, w.category_id, count(w2.score) + 1 rank 
    from winners w left outer join winners w2 
     on w2.category_id = w.category_id and w2.score > w.score 
    group by w.id 
) r 
    on r.id = winners.id 
set winners.rank = r.rank 
+0

Привет @ shawnt00 спасибо за быстрый ответ, но когда я запускаю его MySQL откидывает # 1093 - Вы не можете указать целевую таблицу «победители» для обновления в предложении FROM. – ConorBeckett

+0

привет @ shawnt00 .. большой ответ спасибо .. только один маленький вопрос с ним .. как его можно изменить так, чтобы ряды не пропускали, а были последовательными ... например. (1,2,3,3,3,4,5,6), а не (1,2,3,3,3,6,7,8). cheers – ConorBeckett

+0

Используйте 'count (distinct ...)'. – shawnt00