views:

66

answers:

3

Given a table:

id | score | position
=====================
 1 |    20 |        2
 2 |    10 |        3
 3 |    30 |        1

What query can I use to optimally set the position columns using the (not nullable) score column?

(I'm sure I've seen this before but I can't seem to get the correct keywords to find it!)

+2  A: 
set @rank = 0;
update tbl a join (select score, @rank:=@rank+1 as rank from tbl group by score
  order by score desc) b on a.score = b.score set a.position = b.rank;

to update the position in one fell swoop that would do the trick. equal scores get equal position

Ah, thanks that looks like it and `rank` was the keyword I should have used earlier!
Pool
+1  A: 

Calculate it in the language which you are using. Thus your solution will be:

  • more portable
  • more readable
  • equivalently efficient
Bozho
Thanks, but I'm looking for a solution similar to this: http://stackoverflow.com/questions/1600294/mysql-add-sequence-column-based-on-another-field
Pool
I was trying to hint why such a solution is not that preferable :)
Bozho
+1  A: 
SELECT * FROM your_table ORDER BY score;

Your position column appears to be redundant, although it is hard to tell from the information given in the question. The functionality you appear to want is accomplished using database row ordering, seen in the above example with the 'ORDER BY' expression. Even if you would want a position column for some good reason, remember that most likely there exists an index for the score column anyway, which would in most cases be doing exactly the same thing that a position column would do. Either that, or I completely misunderstand your question.

amn
Thanks amn, yes, position is a redundant but I need to use it for optimisation. Position column would be a cached value of position, created infrequently. (It is very expensive to sort each time I wish to get the position, being set every 5 minutes for example is fine.)
Pool
The optimization is much better done by the database system itself, when you explicitly tell it to index the score column using say the following SQL expression: CREATE INDEX score_index ON your_table(score);
amn
I already do have the score as an index.
Pool
If you have a score as an index, you CANNOT POSSIBLY optimize your ordered score retrieval performance, and I am willing to bet on my statement. Try to benchmark your query for a table with a position column versus the query I have written above - I am betting you will gain nothing from a table with a position. Or, again, I do not understand what you actually want with the table.
amn
I've found a page which shows what I mean. They recorded a 100* performance gain using rank columns http://oreilly.com/pub/a/mysql/2007/03/01/optimize-mysql-rank-data.html?page=6
Pool
Might take me a while to get my head around the information presented in the article, but thanks.
amn
Yes - the justification for taking the action was quite convoluted so I simplified and just detailed the part I was stuck on. It's good to question the motivations though.
Pool