В Извлечена таблица
(подзаявка вътре в FROM
клауза), подреждаме данните си така, че всички редове да имат същия user_id
стойностите се събират заедно с допълнително сортиране между тях въз основа на game_detail
в низходящ ред.
Сега използваме този набор от резултати и използваме условен CASE..WHEN
изрази за оценка на номерирането на редовете. Това ще бъде като техника на Looping (която използваме в кода на приложението, напр.:PHP). Ще съхраняваме стойностите на предишния ред в дефинираните от потребителя променливи и след това ще проверим стойностите на текущия ред спрямо предишния ред. В крайна сметка ще присвоим съответно номер на ред.
Редактиране: Въз основа на MySQL docs и наблюдението на @Gordon Linoff:
Редът на оценка за изрази, включващи потребителски променливи, е недефиниран. Например, няма гаранция, че SELECT @a, @a:[email protected] +1 първо оценява @a и след това изпълнява заданието.
Ще трябва да оценим номера на ред и да зададем user_id
стойност до @u
променлива в рамките на същия израз.
SET @r :=0, @u :=0; SELECT @r :=CASE WHEN @u =dt.user_id THEN @r + 1 WHEN @u :=dt.user_id /* Забележка :=вместо =*/ THEN 1 END AS user_game_rank, dt.user_id, dt.game_detail, dt.game_id FROM ( SELECT user_id, game_id, game_detail FROM game_logs ORDER BY user_id, game_detail DESC ) AS dt
Резултат
<предварителен код>| потребителска_игра_ранг | потребителски_идентификатор | подробности за играта | game_id || -------------- | ------- | ----------- | ------- || 1 | 6 | 260 | 11 || 2 | 6 | 100 | 10 || 1 | 7 | 1200 | 10 || 2 | 7 | 500 | 11 || 3 | 7 | 260 | 12 || 4 | 7 | 50 | 13 |Интересна бележка от MySQL Документи , който открих наскоро:
Предишните версии на MySQL направиха възможно присвояването на стойност на променливата auser в изрази, различни от SET. Тази функционалност се поддържа в MySQL 8.0 за обратна съвместимост, но подлежи на премахване в бъдеща версия на MySQL.
Освен това, благодарение на колега член на SO, попаднах на този блог от MySQL Team:https://mysqlserverteam.com/row-numbering-ranking-how-to-use-less-user-variables-in-mysql-queries/
Общото наблюдение е, че се използва ORDER BY
с оценка на потребителските променливи в същия блок на заявка, не гарантира, че стойностите винаги ще бъдат правилни. Както MySQL оптимизатор може идват на мястото си и променят нашите предполагаеми ред на оценяване.
Най-добрият подход към този проблем би бил да надстроите до MySQL 8+ и да използвате Номер_ред()
функционалност:
Схема (MySQL v8.0)
ИЗБЕРЕТЕ user_id, game_id, game_detail, ROW_NUMBER() НАД (ДЯЛА ПО user_id ПОРЪЧАЙТЕ ПО game_detail DESC) КАТО user_game_rank FROM game_logs ORDER BY user_id, user_game_rank;
Резултат
<предварителен код>| потребителски_идентификатор | game_id | подробности за играта | потребителска_игра_ранг || ------- | ------- | ----------- | -------------- || 6 | 11 | 260 | 1 || 6 | 10 | 100 | 2 || 7 | 10 | 1200 | 1 || 7 | 11 | 500 | 2 || 7 | 12 | 260 | 3 || 7 | 13 | 50 | 4 |