Я пытался ответить другим SO question и неожиданно столкнулся со следующей проблемой. Баллы должны быть назначены на 3 наивысших оценки (mrk
) групп (grp
) каждого класса (sec
). Самые высокие баллы получают 5 очков, второй рейтинг - 3 очка, а группы в 3-м ранге - всего 1 очко. Для всех остальных pts
должно быть установлено значение null
.Как использовать пользовательские переменные в инструкции UPDATE?
| ID | SEC | GRP | MRK | PTS |
|----|-----|-----|-----|--------|
| 1 | cl2 | ge | 32 | (null) |
| 2 | cl1 | gb | 22 | (null) |
| 3 | cl1 | gd | 22 | (null) |
| 4 | cl1 | ge | 18 | (null) |
| 5 | cl2 | ga | 26 | (null) |
| 6 | cl1 | ga | 55 | (null) |
| 7 | cl2 | gb | 66 | (null) |
| 8 | cl2 | gc | 15 | (null) |
| 9 | cl1 | gc | 12 | (null) |
| 10 | cl2 | gf | 5 | (null) |
| 11 | cl2 | ge | 66 | (null) |
Я выбрал для работы с пользовательскими переменными, поскольку они обеспечивают максимальную гибкость в отношении схемы распределения и вскоре пришли к следующему решению:
SELECT id,sec,grp,mrk,
CASE WHEN @s=sec THEN -- whenever there is a new class ...
CASE WHEN @m=mrk THEN @i ELSE -- issue the same points for
-- identical scorers, otherwise ...
CASE WHEN IF(@m:=mrk,@i,@i)>2 THEN @i:[email protected] -- store mrk in @mrk and
-- while @i>2 return points: 3 or 1 ...
ELSE @i:=null -- no points for the rest
END
END
ELSE NULLIF(@i:=5,(@s:=sec)=(@m:=mrk)) -- store sec in @s and mrk in @m
-- and return points: 5
END pts
FROM tbl ORDER BY sec,mrk desc
Объяснение в NULLIF(@i:=5,(@s:=sec)=(@m:=mrk))
:
выражения @s:=sec
и @m:=mrk
оцениваются, а затем их значения сравниваются =
. Результат может быть либо 0
(false), либо 1
(true), но он определенно будет не равным 5
, другому аргументу функции NULLIF
, поэтому в конце будет возвращен только первый аргумент (5
). Я выбрал конструкцию, чтобы сделать два назначения переменных, не возвращая ничего.
ОК, может быть, не самое простое решение ;-), но я сделал обратить внимание определить каждую переменную только один раз для каждой записи, которая обрабатывается, так как «порядок оценки для выражений, включающих пользовательские переменные не определен "mysql manual. select
действительно дает мне нужную
результат:
| ID | SEC | GRP | MRK | PTS |
|----|-----|-----|-----|--------|
| 6 | cl1 | ga | 55 | 5 |
| 2 | cl1 | gb | 22 | 3 |
| 3 | cl1 | gd | 22 | 3 |
| 4 | cl1 | ge | 18 | 1 |
| 9 | cl1 | gc | 12 | (null) |
| 7 | cl2 | gb | 66 | 5 |
| 11 | cl2 | ge | 66 | 5 |
| 1 | cl2 | ge | 32 | 3 |
| 5 | cl2 | ga | 26 | 1 |
| 8 | cl2 | gc | 15 | (null) |
| 10 | cl2 | gf | 5 | (null) |
Теперь мой вопрос:
Как написать UPDATE
заявления по той же схеме, что будет хранить выше вычисленные результаты в столбец pts
?
Мои попытки до сих пор все не удалось:
UPDATE tbl SET pts=
CASE WHEN @s=sec THEN
CASE WHEN @m=mrk THEN @i ELSE
CASE WHEN IF(@m:=mrk,@i,@i)>2 THEN @i:[email protected]
ELSE @i:=null
END
END
ELSE NULLIF(@i:=5,(@s:=sec)=(@m:=mrk))
END
ORDER BY sec,mrk desc
результат:
| ID | SEC | GRP | MRK | PTS |
|----|-----|-----|-----|-----|
| 6 | cl1 | ga | 55 | 5 |
| 2 | cl1 | gb | 22 | 5 |
| 3 | cl1 | gd | 22 | 5 |
| 4 | cl1 | ge | 18 | 5 |
| 9 | cl1 | gc | 12 | 5 |
| 7 | cl2 | gb | 66 | 5 |
| 11 | cl2 | ge | 66 | 5 |
| 1 | cl2 | ge | 32 | 5 |
| 5 | cl2 | ga | 26 | 5 |
| 8 | cl2 | gc | 15 | 5 |
| 10 | cl2 | gf | 5 | 5 |
Почему оператор обновления получить только одно значение (5) для очков?!?
Вы можете найти все данные и инструкции SQL в моем SQLfiddle.
что пожелаете обновить результат. –
@echo_Me мой желаемый результат UPDATE указан в моем сообщении в разделе «Выбор действительно дает мне желаемый результат:». FYI: Я также попытался вставить вывод SELECT в (временную) таблицу -> тот же результат, что и в нижней части моего сообщения :-( – cars10m