Hello StackOverflow community:
The Situation
I am building an update query that sets ranks for all records in a table according to how each record compares to each other. Example of table:
id | budget | cost | rank | rank_score
1 | 500 | 20 | ? | ?
2 | 400 | 40 | ? | ?
3 | 300 | 40 | ? | ?
So in this table, cost
have the most weight in determining rank, followed by budget
. Thus, record #2 will rank higher, while record #3 will be second and #1 will be last. As you can see, if two records have the same cost
, then budget
breaks the tie.
Now, In order to keep track of such 'weight' easily, I'm creating the rank_score
column, which will hold the concatenation of cost
and budget
. Thus the rank_score
for the table above would be:
id | budget | cost | rank | rank_score
1 | 500 | 20 | ? | 20500
2 | 400 | 40 | ? | 40400
3 | 300 | 40 | ? | 40300
This rank_score
can be filled like:
UPDATE table_name
SET rank_score = CONCAT(cost, budget);
The Problem
Everything alright so far. But now comes the problem. I need an integer-only rank
column for several stuff like sorting, but above all for showing the user the rank of his record. Of course, this rank
column will be equal to the descending order of the rank_scores. But I cannot find a way to calculate this rank
column in a single update query without having to do subqueries, loops in php, etc.
What I Have Tried
So, at first I was trying to fetch the rank_score
calculation like:
SELECT id,
CONCAT(cost, budget) AS rank_score
FROM table_name ;
and then looping in php all those rank_scores, only to build a query that went like:
UPDATE table_name
SET rank_score = CASE id WHEN 1 THEN 20500 END,
rank = CASE id WHEN 1 THEN 3 END
WHERE id IN (1) ;
... Of course, this sample update query is not complete, as it has more WHEN THEN END
clauses for each record in the table. Needless to say, this is ugly, especially when you expect to be having thousands and thousands of records.
So, in conclusion, I already have a way for calculating rank_score
, but I also want to calculate rank
(= descending order of rank score) in the same query, or at least without doing that crazy php looping and CASE WHEN THEN END
clauses.
Thank You for Reading and Thinking About This ;)
Clarifications
Clarifying what @SJuan76 said:
I cannot assign a rank via php since there are instances when the user will be shown a fixed quantity of records at a time (example, his user page: SELECT * WHERE user_id = 333
, which could fetch 1, 3 or 8 records) and he needs to know what's the rank for each record. Assigning a rank via php in that case doesn't work because such rank will be relative to fetched records, not to all in table.