I en Härledd tabell
(underfråga i FROM
klausul), ordnar vi vår data så att alla rader har samma user_id
värden kombineras, med ytterligare sortering mellan dem baserat på game_detail
i fallande ordning.
Nu använder vi denna resultatuppsättning och använder villkorlig CASE..WHEN
uttryck för att utvärdera radnumreringen. Det kommer att vara som en Looping-teknik (som vi använder i applikationskod, t.ex. PHP). Vi skulle lagra de tidigare radvärdena i de användardefinierade variablerna och sedan kontrollera den aktuella radens värden mot föregående rad. Så småningom kommer vi att tilldela radnummer i enlighet med detta.
Redigera: Baserat på MySQL dokument och @Gordon Linoffs observation:
Utvärderingsordningen för uttryck som involverar användarvariabler är odefinierad. Det finns till exempel ingen garanti för att SELECT @a, @a:[email protected] +1utvärderar @a först och utför sedan uppgiften.
Vi kommer att behöva utvärdera radnummer och tilldela user_id
värde till @u
variabel inom samma uttryck.
SET @r := 0, @u := 0;
SELECT
@r := CASE WHEN @u = dt.user_id
THEN @r + 1
WHEN @u := dt.user_id /* Notice := instead of = */
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
Resultat
| user_game_rank | user_id | game_detail | 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 |
En intressant anteckning från MySQL Dokument , som jag upptäckte nyligen:
Tidigare utgåvor av MySQL gjorde det möjligt att tilldela ett värde till auser-variabeln i andra satser än SET. Den här funktionen stöds i MySQL 8.0 för bakåtkompatibilitet men kan tas bort i en framtida version av MySQL.
Tack vare en SO-medlem kom också över den här bloggen av MySQL Team:https://mysqlserverteam.com/row-numbering-ranking-how-to-use-less-user-variables-in-mysql-queries/
Allmän observation är att använda ORDER BY
med utvärdering av användarvariablerna i samma frågeblock säkerställer inte att värdena alltid är korrekta. Som, MySQL optimizer kan komma på plats och ändra våra förmodade ordning för utvärdering.
Bästa tillvägagångssättet för detta problem skulle vara att uppgradera till MySQL 8+ och använda Row_Number()
funktionalitet:
Schema (MySQL v8.0)
SELECT user_id,
game_id,
game_detail,
ROW_NUMBER() OVER (PARTITION BY user_id
ORDER BY game_detail DESC) AS user_game_rank
FROM game_logs
ORDER BY user_id, user_game_rank;
Resultat
| user_id | game_id | game_detail | user_game_rank |
| ------- | ------- | ----------- | -------------- |
| 6 | 11 | 260 | 1 |
| 6 | 10 | 100 | 2 |
| 7 | 10 | 1200 | 1 |
| 7 | 11 | 500 | 2 |
| 7 | 12 | 260 | 3 |
| 7 | 13 | 50 | 4 |