Reputation: 301
Rank Table
NAME, The associated name of the rank
Rank Table
+----+------+-----------+-------------------------+
| ID | RANK | MIN_SCORE | NAME |
+----+------+-----------+-------------------------+
| 1 | 1 | 18932 | Editor-in-Chief |
| 2 | 2 | 15146 | Senior Technical Writer |
| 3 | 3 | 12116 | Senior Copywriter |
+----+------+-----------+-------------------------+
Ranking Table
SCORE, The member's current earned score or XP
Ranking Table
+-----+--------------+---------+-------+
| ID | FK_MEMBER_ID | FK_RANK | SCORE |
+-----+--------------+---------+-------+
| 1 | 1 | 1 | 17722 |
| 2 | 2 | 2 | 16257 |
| 3 | 3 | 3 | 12234 |
+-----+--------------+---------+-------+
In my class I have stored the ranks -- matching those in the Rank Table -- and correlating minimum scores; RANK as key and MINIMUM_SCORE as value.
When a member's score (XP) is updated (up/down) I want to test that updated score against the below array to determine if their rank needs updating too.
private $scores = array('3' => '12116', '2' => '15146', '1' => '18932',);
Using the updated score, how could I determine the correlating rank from the above array?
Everything is open to scrutiny, this is my first time creating a ranking system so I hope to get it right :)
Upvotes: 0
Views: 386
Reputation: 54242
Ok, so given these tables:
Ranks
+------+-----------+-------------------------+
| RANK | MIN_SCORE | NAME |
+------+-----------+-------------------------+
| 1 | 18932 | Editor-in-Chief |
| 2 | 15146 | Senior Technical Writer |
| 3 | 12116 | Senior Copywriter |
+------+-----------+-------------------------+
Members
+-----------+-------+
| MEMBER_ID | SCORE |
+-----------+-------+
| 1 | 17722 |
| 2 | 16257 |
| 3 | 12234 |
+-----+-------------+
You can get a member plus their rank using:
SELECT m.MEMBER_ID, r.NAME
FROM Members m INNER JOIN Ranks r
ON m.SCORE > r.MIN_SCORE -- Pick ranks that a user is eligible for
WHERE MEMBER_ID = ?
HAVING MAX(r.MIN_SCORE) -- Pick the rank with the highest score
This allows you remove an entire table, which should make your code easier to maintain. Hopefully your rank table will be so small than it will always be in memory, but an index over both MIN_SCORE
and RANK
will probably be helpful.
If you determine that this join is a performance problem (please don't do this unless you've measured a performance problem), you can use a similar query to update ranks in the members table, assuming it has a RANK
column:
UPDATE Members
SET RANK = (
SELECT RANK
FROM Ranks
WHERE SCORE > MIN_SCORE
AND MEMBER_ID = MEMBER_ID
HAVING MAX(MIN_SCORE)
)
Upvotes: 1