mysql 多列比较,根据MySQL中的多列确定排名

I have a table which has 3 fields, I want to rank column based on user_id and game_id.

the table already I have :

user_id | game_id | game_detial_sum |

--------|---------|--------------------|

6 | 10 | 1000 |

6 | 11 | 260 |

7 | 10 | 1200 |

7 | 11 | 500 |

7 | 12 | 360 |

7 | 13 | 50 |

expected output :

user_id | game_id | game_detial_sum | user_game_rank |

--------|---------|--------------------|------------------|

6 | 10 | 1000 | 1 |

6 | 11 | 260 | 2 |

7 | 10 | 1200 | 1 |

7 | 11 | 500 | 2 |

7 | 12 | 360 | 3 |

7 | 13 | 50 | 4 |

My efforts so far :

SET @s := 0;

SELECT user_id,game_id,game_detail,

CASE WHEN user_id = user_id THEN (@s:=@s+1)

ELSE @s = 0

END As user_game_rank

FROM game_logs

Edit: (From OP Comments): Ordering is based on the descending order of game_detail

order of game_detail

解决方案

In a Derived Table (subquery inside the FROM clause), we order our data such that all the rows having same user_id values come together, with further sorting between them based on game_detail in Descending order.

Now, we use this result-set and use conditional CASE..WHEN expressions to evaluate the row numbering. It will be like a Looping technique (which we use in application code, eg: PHP). We would store the previous row values in the User-defined variables, and then check the current row's value(s) against the previous row. Eventually, we will assign row number accordingly.

Edit: Based on MySQL docs and @Gordon Linoff's observation:

The order of evaluation for expressions involving user variables is

undefined. For example, there is no guarantee that SELECT @a, @a:=@a+1

evaluates @a first and then performs the assignment.

We will need to evaluate row number and assign the user_id value to @u variable within the same expression.

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

Result

| 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 |

An interesting note from MySQL Docs, which I discovered recently:

Previous releases of MySQL made it possible to assign a value to a

user variable in statements other than SET. This functionality is

supported in MySQL 8.0 for backward compatibility but is subject to

removal in a future release of MySQL.

General observation is that using ORDER BY with evaluation of the user variables in the same query block, does not ensure that the values will be correct always. As, MySQL optimizer may come into place and change our presumed order of evaluation.

Best approach to this problem would be to upgrade to MySQL 8+ and utilize the Row_Number() functionality:

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;

Result

| 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 |

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值