I am trying to update position for my player in present in table. This table consists of name , id, points and position.
Default value of points is 0
then position will be Unranked
.
If two users have same points then there positions will be same.
Demo table
id | name | points | position
1 | a | 0 | Unranked
2 | b | 120 | 2
3 | c | 130 | 3
4 | d | 120 | 1
Required result should be
id | name | points | position
1 | a | 0 | Unranked
2 | b | 120 | 2
3 | c | 130 | 1
4 | d | 120 | 2
Query will be like for unranked update mytable set position = 'Unranked' Where points = 0
How will i use points and position set query ?
This is a pain. You can get the results you want with a subquery, but that doesn't quite work in an update
clause. In a select
, you can do:
select t.*,
(select 1 + count(*)
from t t2
where t2.points > 0 and t2.points > t.points
) as rank
from t;
You can now incorporate this into an update:
update t join
(select t.*,
(select 1 + count(*)
from t t2
where t2.points > 0 and t2.points > t.points
) as new_position
from t;
) tt
on t.id = tt.id
set t.position = tt.new_position
where t.points > 0;
There's no need to hold the computed column position
in the table. The following works for all versions :
create table tab ( id int, name varchar(1), points int );
insert into tab values
(1,'a', 0),
(2,'b',120),
(3,'c',130),
(4,'d',120);
select t.id, t.name, t.points,
( case when points = 0 then 'Unranked' else t.rnk end ) as position
from
(
select t1.*,
@rnk := if(@pnt = points,@rnk,@rnk + 1) rnk,
@pnt := points
from tab t1
cross join (select @rnk := 0, @pnt := 0 ) t2
order by points desc
) t
order by t.id;
id name points position
-- ---- ------ --------
1 a 0 Unranked
2 b 120 2
3 c 130 1
4 d 120 2
If you want to hold the column position
in your table, then you can use the following update
statement by binding through primary column id
:
update tab tt
set position = ( select
( case when points = 0 then 'Unranked' else t.rnk end ) as position
from
(
select t1.*,
@rnk := if(@pnt = points,@rnk,@rnk + 1) rnk,
@pnt := points
from tab t1
cross join (select @rnk := 0, @pnt := 0 ) t2
order by points desc
) t
where t.id = tt.id );
If your version of MySQl (MySQL 8.x) supports window function then following is possible:
SELECT name,
RANK() OVER (
ORDER BY points DESC
) position
FROM mytable
where points != 0
Selected data can be then joined for the update like in the answer from Gordon Linoff.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.