tags:

views:

58

answers:

1

I have a column I want to sort by, with periodical updates on the rank (daily). I currently use this in code

get all rows from table order by column

rank = 1
foreach row in table
   update row's rank to rank
   rank++

this takes an update for each row in MySQL. Are there more efficient ways to do this?

+3  A: 

Use an update with a join:

set @rank := 0;

update tbl a join
  (select id, @rank := @rank + 1 as new_rank from tbl order by col) b
  on a.id = b.id set a.rank = b.new_rank;

If expecting to have a lot of rows, you'll get the best performance by doing the join against a table that is indexed, e.g.:

set @rank := 0;

create temporary table tmp (id int primary key, rank int)
  select id, @rank := @rank + 1 as rank from tbl order by col;

update tbl join tmp on tbl.id = tmp.id set tbl.rank = tmp.rank;

Finally, you could potentially make it faster by skipping the update step entirely and swapping in a new table (not always feasible):

set @rank := 0;

create table new_tbl (id int primary key, rank int, col char(10),
  col2 char(20)) select id, @rank := @rank + 1 as rank, col, col2
  from tbl order by col;

drop table tbl;
rename table new_tbl to tbl;
jspcal
Thanks, upvoted you. Any idea what this complexity is? Assuming all obvious optimizations (keys, etc) are taken?
Timmy
yeah best performance is when there's an index, theoretically it should then be rather linear since the primary key is a hash, and you would be updating all the items in the table
jspcal
Probably n log n is okay, as long as it doesn't dip into quadratic territory. I've done some testing and it's substantially faster, even for small values of N. Only issue might be possible table lock, which I should look into (or maybe de-normalize it to its own table)..
Timmy