Next and Previous MySQL row based on name - php

I have a table with details on personnel. I would like to create a Next/Previous link based on the individual's last name. Since personnel were not added in alphabetical order, selecting the next or previous row based on its ID does not work.
It is a hefty table - the pertinent fields are id, name_l, and name_f. I would like to order by name_l, the individuals' last name.
How would I go about accomplishing this task?
Thanks!
Edit
This will be used on a Personnel Details page, the result will generate links to the next/prev entry in the database (ordered by last name) based on the current row. For example, if I am viewing Joe Hammer, the Next link would link to Frank Ingram.
Final code
Thanks to Daniel, here is what I finally got to work:
First, I set an increment at 0: $i = 0. Then, while looping through records with a while loop, I increased this by 1 = $i++. I then made a link to the details page for that particular entry:
Details
On the Details page, I used the following SQL to select the next record:
$row = $_GET['row'];
$getNext = mysql_query("SELECT * FROM members ORDER BY name_l, id LIMIT ".$row.", 1");
$next = mysql_fetch_assoc($getNext);
$nextLink = $row + 1;
Finally, the link:
<?php echo $next['name_l'] . ", " . $next['name_f'];?>

First of all, make sure that your name_l column is indexed. Then you can simply use the ORDER BY and the LIMIT clauses as follows:
SELECT * FROM personnel ORDER BY name_l, id LIMIT 0, 1;
Simply increment the 0 value in the LIMIT clause to select the next record within the ordered set. Therefore use LIMIT 1, 1 to get the second record, LIMIT 2, 1 for the third, etc.
To create an index on name_l you can use the CREATE INDEX command:
CREATE INDEX ix_index_name ON personnel (name_l);
Test case:
CREATE TABLE personnel (
id int not null primary key,
name_l varchar(10),
name_f varchar(10)
);
CREATE INDEX ix_last_name_index ON personnel (name_l);
INSERT INTO personnel VALUES (1, 'Pacino', 'Al');
INSERT INTO personnel VALUES (2, 'Nicholson', 'Jack');
INSERT INTO personnel VALUES (3, 'De Niro', 'Robert');
INSERT INTO personnel VALUES (4, 'Newman', 'Paul');
INSERT INTO personnel VALUES (5, 'Duvall', 'Robert');
Results:
SELECT * FROM personnel ORDER BY name_l, id LIMIT 0, 1;
+----+---------+--------+
| id | name_l | name_f |
+----+---------+--------+
| 3 | De Niro | Robert |
+----+---------+--------+
1 row in set (0.00 sec)
SELECT * FROM personnel ORDER BY name_l, id LIMIT 1, 1;
+----+--------+--------+
| id | name_l | name_f |
+----+--------+--------+
| 5 | Duvall | Robert |
+----+--------+--------+
1 row in set (0.00 sec)
SELECT * FROM personnel ORDER BY name_l, id LIMIT 2, 1;
+----+--------+--------+
| id | name_l | name_f |
+----+--------+--------+
| 4 | Newman | Paul |
+----+--------+--------+
1 row in set (0.00 sec)
1st UPDATE: (Further to the comments below)
The above example is suitable mainly if you start by displaying the first record, and then you move sequentially to next, and maybe next again, and perhaps one back, etc. You could also easily move x steps forward and x steps backwards, but this does not appear to be required.
If you start from a random record however, it will be more difficult to adapt the query above to get the next and previous records.
If this is the case, then you can simply keep an index counter of where you currently stand. You start with $index = 0, and display the first record by using ... LIMIT $index, 1. Then you display the next by incrementing $index by 1, and you display the previous by decrementing $index by 1.
If on the other hand, you will be rendering the personnel list, and then the user will click on one record (at random), you could also make this work with some help from the applications-side (php). Let's say you render the following ordered list to the user:
+----+-----------+--------+
| id | name_l | name_f |
+----+-----------+--------+ // [Hidden info]
| 3 | De Niro | Robert | // Row 0
| 5 | Duvall | Robert | // Row 1
| 4 | Newman | Paul | // Row 2
| 2 | Nicholson | Jack | // Row 3
| 1 | Pacino | Al | // Row 4
+----+-----------+--------+
Now if the user clicks on Newman Paul, you would have to pass the row=2 parameter to the page that will display the details of this employee. The page that renders the details of the employee now knows that Newman Paul is the 3rd row (row=2). Therefore to get the previous and the next records you would simply change the x in LIMIT x, 1 by row - 1 for the previous record and row + 1 for the next:
-- Previous
SELECT * FROM personnel ORDER BY name_l, id LIMIT 1, 1;
+----+--------+--------+
| id | name_l | name_f |
+----+--------+--------+
| 5 | Duvall | Robert |
+----+--------+--------+
1 row in set (0.00 sec)
-- Next
SELECT * FROM personnel ORDER BY name_l, id LIMIT 3, 1;
+----+-----------+--------+
| id | name_l | name_f |
+----+-----------+--------+
| 2 | Nicholson | Jack |
+----+-----------+--------+
1 row in set (0.00 sec)
2nd UPDATE:
You can use the following MySQL-specific query to get the record number within the ordered list of any random employee, which then can be used to get the previous and next records. Note however that this is not very efficient, and may degrade performance if you have thousands of records.
Let's say you are in employee Nicholson Jack.
You could do the following query:
SELECT p.id, p.name_l, p.name_f, o.record_number
FROM personnel p
JOIN (
SELECT id,
#row := #row + 1 AS record_number
FROM personnel
JOIN (SELECT #row := -1) r
ORDER BY name_l, id
) o ON (o.id = p.id)
WHERE p.name_l = 'Nicholson' AND p.name_f = 'Jack';
Which returns this:
+----+-----------+--------+---------------+
| id | name_l | name_f | record_number |
+----+-----------+--------+---------------+
| 2 | Nicholson | Jack | 3 |
+----+-----------+--------+---------------+
1 row in set (0.00 sec)
Note that in the WHERE clause you could have used p.id = 2 if the id is known, instead of p.name_l = 'Nicholson' AND p.name_f = 'Jack'.
Now we can use the record_number field, which is 3 in this case, to get the previous and the next records, simply by using the original query from the top of this answer, and replacing LIMIT 2, 1 for the previous and LIMIT 4, 1 for the next. There you go:
The previous of Nicholson Jack:
SELECT * FROM personnel ORDER BY name_l, id LIMIT 2, 1;
+----+--------+--------+
| id | name_l | name_f |
+----+--------+--------+
| 4 | Newman | Paul |
+----+--------+--------+
1 row in set (0.00 sec)
The next from Nicholson Jack:
SELECT * FROM personnel ORDER BY name_l, id LIMIT 4, 1;
+----+--------+--------+
| id | name_l | name_f |
+----+--------+--------+
| 1 | Pacino | Al |
+----+--------+--------+
1 row in set (0.00 sec)

Try a better SQL SELECT statement:
SELECT * FROM tblPersonnel ORDER BY name_l ASC
Try this link for more info:
http://w3schools.com/sql/sql_orderby.asp

Related

order table when making an update

I have the following table where order by priority ASC
----------------------
|priority |activity |
|---------|-----------|
| 1 |act1 |
| 2 |act2 |
| 3 |act3 |
| 4 |act4 |
| 5 |act5 |
|---------|-----------|
JSON where I make an update.
Add Method but it does not work as I wish
<?php
//update.php
include_once('../include/conexion.php');
$query = "
UPDATE ACT_schedule SET ".$_POST["name"]." = '".$_POST["value"]."'
WHERE id_schedule = '".$_POST["pk"]."'";
$result=mysqli_query($conn, $query);
if ($result) {
$query2 = "UPDATE ACT_Agenda SET prioridad = CASE
WHEN prioridad >= " . $_POST['value'] . "
THEN prioridad + 1 ELSE prioridad END
WHERE id_agenda <> '" . $_POST['pk'] . "'";
mysqli_query($conn, $query2);
echo "YES";
} ?>
What I want to do is order the priority, if I update the act5 that has priority 5 to priority 1, the priority changes and that means that the priority of the act1 must change to 2 and so on until the act4 change to priority 5.
It works well if I update the last priority. But if I update the act4 to priority 1 the ones below should not be updated but they do it by adding +1 (act5 priority 5 is 6).
Something like that I would like if I update act4 to priority 1
----------------------
|priority |activity |
|---------|-----------|
| 1 |act4 |
| 2 |act1 |
| 3 |act2 |
| 4 |act3 |
| 5 |act5 |
|---------|-----------|
I hope I explained well. Greetings.
From your code it's not 100% clear which are the appropriate $_POST variables to use in the update query so here is a pure MySQL solution. First create the demo table:
CREATE TABLE agenda (`priority` int, `activity` varchar(4));
INSERT INTO agenda (`priority`, `activity`)
VALUES (1, 'act1'), (2, 'act2'), (3, 'act3'), (4, 'act4'), (5, 'act5');
SELECT * FROM agenda ORDER BY priority;
Output:
priority activity
1 act1
2 act2
3 act3
4 act4
5 act5
To update, use the following query. I have used variables #n for the new priority and #a for the activity to modify; in your PHP code you would remove the SET statements below and replace #n and #p in the update query with the appropriate $_POST values. In this example I am shifting act4 to priority 2:
SET #a = 'act4';
SET #n = 2;
UPDATE agenda SET priority = CASE WHEN priority BETWEEN #n AND (SELECT * FROM (SELECT priority FROM agenda WHERE activity=#a) a) AND activity != #a THEN priority + 1
WHEN activity = #a THEN #n
ELSE priority
END;
Now we can look at the modified table:
SELECT * FROM agenda ORDER BY priority;
Output:
priority activity
1 act1
2 act4
3 act2
4 act3
5 act5
SQLFiddle Demo
This can be achieved all inside the database. Please see the following example proof:
First the boring part where I created your table and inserted your sample data:
mysql> CREATE TABLE priority_demo (priority SMALLINT UNSIGNED, activity VARCHAR(4));
Query OK, 0 rows affected (0.06 sec)
mysql> INSERT INTO priority_demo VALUES (1, 'act1');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO priority_demo VALUES (2, 'act2'), (3, 'act3'),(4, 'act4'), (5,'act5');
Query OK, 4 rows affected (0.02 sec)
mysql> SELECT * FROM priority_demo;
+----------+----------+
| priority | activity |
+----------+----------+
| 1 | act1 |
| 2 | act2 |
| 3 | act3 |
| 4 | act4 |
| 5 | act5 |
+----------+----------+
5 rows in set (0.00 sec)
Now, as an example, I'm changing the priority of act4 (currently prio 4) to new value 2. As my example is generic then I'm gonna use internal variables for both current and new priority for the specific activity, whereas ideally instead of #activity_key and #new you'd use your php variables when constructing the query:
mysql> SET #activity_key := 'act4', #new = 2; -- variables from php
Query OK, 0 rows affected (0.00 sec)
For demo purposes I'm outputting them too:
mysql> SELECT #activity_key, #new; -- variables used below
+---------------+------+
| #activity_key | #new |
+---------------+------+
| act4 | 2 |
+---------------+------+
Ok, we're ready to act now.
First the most interesting query - the UPDATE with priority changes.
As pulling the current priority out of the database is un-necessary overhead and useless round trip, I've implemented 3rd MySQL variable here, called #cur which contains the current value, so the update query below would know if and where and what to change.
We run the 2 following queries (SET #cur ... and UPDATE ...) together as one batcho. This ensures that it's not gonna change anything if already changed:
mysql> -- both in one "batch"
-> SET #cur := (SELECT priority FROM priority_demo WHERE activity=#activity_key LIMIT 1);
-> UPDATE priority_demo SET priority=CASE
-> WHEN priority >= #new AND priority < #cur THEN priority+IF(#cur<>#new, 1,0)
-> WHEN activity = #activity_key THEN #new ELSE priority END;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 5 Changed: 0 Warnings: 0
Let's see the result:
mysql> SELECT * FROM priority_demo; -- result as is
+----------+----------+
| priority | activity |
+----------+----------+
| 1 | act1 |
| 3 | act2 |
| 4 | act3 |
| 2 | act4 |
| 5 | act5 |
+----------+----------+
5 rows in set (0.00 sec)
mysql> SELECT * FROM priority_demo ORDER BY priority; -- priority ordered view
+----------+----------+
| priority | activity |
+----------+----------+
| 1 | act1 |
| 2 | act4 |
| 3 | act2 |
| 4 | act3 |
| 5 | act5 |
+----------+----------+
5 rows in set (0.00 sec)
Even if you reran the query again, it wouldn't change anything. That's because of the IF(...) part of the UPDATE above.
EDIT: I just discovered that my answer is somewhat similar to #nicks, but that's ok, I guess, as my proposed implementation can be safely executed in a "shoot firt, ask questions later" manner ;)
I got your point... Basically you need to edit sort order numbers in your column Priority...
is your priority colum is primary ? or separate id column is there in your mysql table.. ? if separate primary id column doesn't exist.. create it and keep this priority column separate, so you can change/update sort numbers in this column....
in your ajax update script..i.e.... updatePriorityJSON.php.... you will need code somewhat like..
this is not tested.. but given as sample...
for($i=0; $i<count($_POST["priority"]); $i++) {
$query = "
UPDATE table
SET priority = '".$i."'
WHERE id = '".$_POST["id"][$i]."'";
}
more tutorial point of view, please view https://www.webslesson.info/2017/06/sorting-table-row-using-jquery-drag-drop-with-ajax-php.html?m=1
Please take care for prevention of any SQL injection through this code
After updating act5 priority to 1: (*)
UPDATE ACT_Agenda SET priority = 1 WHERE activity = 'act5';
Check to see the other records that need to be updated:
SELECT * FROM ACT_Agenda WHERE priority >= 1 AND activity <> 'act5';
Then update the priority: (*)
UPDATE ACT_Agenda SET priority = priority+1 WHERE priority >= 1 AND activity <> 'act5';
(*) last step is to implement this sql to your code

How do I get distinct rows by a column?

I have a huge number of rows that I'd like to get say, last 5 records inserted in that database from 10 different users. If the same user inserted the last 3 rows into database, we must get one row, skip the others two and move to get a row per user, until it count up to 5.
A database like that:
user_id | news_id | title
1 | 1 | foo-1
2 | 2 | foo-2
3 | 3 | foo-3
1 | 4 | baa
4 | 5 | baa0
5 | 6 | baa1
5 | 7 | baa2
6 | 8 | baa3
7 | 9 | baa4
Should return:
user_id | news_id | title
1 | 1 | foo-1
2 | 2 | foo-2
3 | 3 | foo-3
4 | 5 | baa0
5 | 6 | baa1
The current filter was done by PHP, like this:
$used = array();
while ($data = mysql_fetch_array($query)) {
$uid = $data['user_id'];
if(in_array($uid, $used))
continue;
array_push($used, $uid);
// do something with data
}
But I want to refactor it, and do the filter purely by mysql, if possible. I don't know much MySql and that's why I'm having problem to archive this...
Here's what I've tried
select DISTINCT(user_id), news_id, title from XXX
WHERE GROUP BY (news_id) DESC
LIMIT 0,5
How can I do that?
1 way you can do it is to generate a partitioned row number per user and then select 5 records where RowNumber = 1.
SELECT *
FROM
(
SELECT
d.user_id
,d.news_id
,d.title
,(#rn:= if(#uid = user_id, #rn + 1,
if(#uid:=user_id,1,1)
)
) as RowNumber
FROM
Data d
CROSS JOIN (SELECT #uid:=-1, #rn:=0) vars
ORDER BY
user_id
,news_id
) t
WHERE
t.RowNumber = 1
ORDER BY news_id
LIMIT 5;
http://rextester.com/JRIZI7402 - example to show it working
Note you can change the row order by simply changing the ORDER BY statement of the derived table so if you have a column that will signify the latest record e.g. an identity column or a datetime column you can use that, but user_id must be the first criteria to be partitioned correctly.
Do it from your query.
"SELECT * FROM table GROUP BY user_id ORDER BY news_id DESC LIMIT 5"
well, i think this will achieve what you are after.
select user_id, news_id, title from tableName
GROUP BY user_id
ORDER BY news_id DESC
LIMIT 0,5
Hope this helps!

Php/mysql ranking system - Placement inside a result set ordered by column

In a blog-like website, all the users can "star" a news (= bookmark it, mark it as "favourite").
I have a mysql table for stats.
table_news_stats
id_news
total_stars (int) //Total number of users who starred this news
placement (int)
The placement field is intuitive: if you order all the news by the total_stars field you get each news placement. So, the news with most stars will be number 1, and so on.
So, suppose I have 700 records in my table_news_stats, and for each one I have the id and the total_stars count, how can I update the placement field automatically for each record? Which query is faster/better?
Example of the table_news_stats content:
First record (A):
1-3654-?
Second record (B):
2-2456-?
Third record (C):
3-8654-?
If you order the record by stars count:
the sequence of records is C - A - B
So... the result will be:
First record (A):
1-3654-2
Second record (B):
2-2456-3
Third record (C):
3-8654-1
Clarification:
why would I ever need the placement field at all?
It's pretty simple... the placement field will be populated by a cronjob the first day of every month. Basically it will provide a 'snapshot' of the rank of each news in terms of popularity (as it was at the beginning of the current month). As a consequence, thanks to the placement field, I will have the following information:
"The 1st day of this month the 'top starred' news list was like this:
1- News C
2- NewsA
3- News B "
Then, with a query "SELECT * FROM table_news_stats ORDER BY total_stars DESC" I can obtain the new ranking (in real-time).
As a consequence, I will have the following information:
"At the time the page is loaded, the 'top starred' news list is like this:
1- News A
2- News C
3- News B "
Finally, by comparing the two rankings, I obtain the last piece of information:
"News A has gained a position" +1
"News C has lost a position" -1
"News B has no change in position" +0
If there is a better way of doing this, let me know.
I guess you don't need to update the table just:
SELECT *
FROM table_news_stats
ORDER BY total_stars DESC
But if you want to know the place of each one you can:
SELECT *, IF(#idx IS NULL,#idx:= 1,#idx:= #idx+1)
FROM table_news_stats
ORDER BY total_stars DESC
And if you still need to update something like:
UPDATE table_news_stats
SET placement = FIND_IN_SET(id_news,(SELECT GROUP_CONCAT(t.id_news) FROM (SELECT id_news
FROM table_news_stats
ORDER BY total_stars DESC) t ))
SQLFiddle
Consider the following
mysql> select * from test ;
+------+-------------+-----------+
| id | total_stars | placement |
+------+-------------+-----------+
| 1 | 3 | 0 |
| 2 | 6 | 0 |
| 3 | 7 | 0 |
| 4 | 2 | 0 |
| 5 | 9 | 0 |
| 6 | 2 | 0 |
| 7 | 1 | 0 |
+------+-------------+-----------+
Now using the following you can update the placement as
update test t1 join
(
select *,
#rn:= if(#prev = total_stars,#rn,#rn+1) as rank ,
#prev:= total_stars
from test,(select #rn:=0,#prev:=0)r
order by total_stars desc
)t2
on t2.id = t1.id
set t1.placement = t2.rank ;
mysql> select * from test order by placement ;
+------+-------------+-----------+
| id | total_stars | placement |
+------+-------------+-----------+
| 5 | 9 | 1 |
| 3 | 7 | 2 |
| 2 | 6 | 3 |
| 1 | 3 | 4 |
| 4 | 2 | 5 |
| 6 | 2 | 5 |
| 7 | 1 | 6 |
+------+-------------+-----------+
Note that in case of tie will have the same placement.

How best to get someone's 'rank' from a scores table with php and mysql without looping

My table will hold scores and initials.
But the table wont be ordered.
I can get the total row count easy enough and I know I can get all of them and Order By and then loop through them and get the rank THAT way...
But is there a better way? Could this maybe be done with the SQL statement?
I'm not TOO concerned about performance so if the SQL statement is some crazy thing, then Ill just loop.
Sorry - Table has id as primary key, a string to verify unique app install, a column for initials and a column for score.
When someone clicks GET RANK... I want to be able to tell them that their score is 100 out of 1000 players.
SELECT s1.initials, (
SELECT COUNT(*)
FROM scores AS s2
WHERE s2.score > s1.score
)+1 AS rank
FROM scores AS s1
Do you have a primary key for the table or are you fetching data by the initials or are you just fetching all the data and looping through it to get the single record? How many results are you trying to fetch?
If you only want to fetch one record, as the title suggests, you would query the database using a WHERE conditional:
SELECT score FROM table WHERE user_id = '1';
See this answer: https://stackoverflow.com/a/8684441/125816
In short, you can do something like this:
SELECT id, (#next_rank := IF(#score <> score, 1, 0)) nr,
(#score := score) score, (#r := IF(#next_rank = 1, #r + 1, #r)) rank
FROM rank, (SELECT #r := 0) dummy1
ORDER BY score DESC;
And it will produce a result like this:
+------+----+-------+------+
| id | nr | score | rank |
+------+----+-------+------+
| 2 | 1 | 23 | 1 |
| 4 | 1 | 17 | 2 |
| 1 | 0 | 17 | 2 |
| 5 | 1 | 10 | 3 |
| 3 | 1 | 2 | 4 |
+------+----+-------+------+
Note that users with equal scores have equal ranks. :-)

Group and Rank Rows in Mysql

I'm trying to build a ranking system in a mysql database.
I've found several tutorials on ranking and items here on StackOverflow about ranking individual rows against each other.
However, my issue is that I need to group rows by a user id column, add up the values to a second column grouped by user id, then rank them against other groups of a different user id.
Here's an example of the table I'm using:
user_id km_skied date_entered
1 34 2010-08-19
3 2 2010-08-23
1 3 2010-08-13
4 23 2010-08-01
3 5 2010-08-02
The result printout would be by rank:
Skier Rank:
Rank User ID Total KM
1 1 37
2 4 23
3 3 7
Also, I was wondering how I find the rank for a specific user. Meaning, if I know what the user id is, can I give them just their rank? Like say
"Your Rank: 2 of 345"
That is the second part of this.
Anyone know how to do that?
Thanks!
Troy
Your query should look something like this. Add the ranking logic to the outer loop.
select * from
(select user_id, sum(km_skied) as km from ski group by user_id) x
order by x.km desc;
Don't know if it's an option, but you can use a temporary table for rankings as follows:
create temporary table ranks (rank int primary key auto_increment, user_id int, km int);
insert into ranks (user_id, km)
select user_id, km from (
select user_id, sum(km_skied) as km from ski group by user_id
) x order by x.km desc;
This gives you what you want:
mysql> select * from ranks;
+------+---------+------+
| rank | user_id | km |
+------+---------+------+
| 1 | 1 | 37 |
| 2 | 4 | 23 |
| 3 | 3 | 7 |
+------+---------+------+
3 rows in set (0.00 sec)
One downside to this approach is that skiers who are tied won't get the same rank.
Do the grouping in subquery and ranking of the results (using any of the methods you've found before) in outer query.
Thanks for your help guys.
I was able to come up with an answer based on the following Query:
$totalQuery = "SELECT SUM(track_length) as usertracklength, username, MAX(track_create_time) as lasttrack, count(DISTINCT track_create_time) as totaldays FROM user_tracks GROUP BY username ORDER BY usertracklength DESC";
$totalResult = mysql_query($totalQuery);
$rankResult = mysql_query($totalQuery);
$totalNumEntries = mysql_num_rows($totalResult);
Then Ouputting that to an array
// rank position array
$rankArray = array();
while ($row1 = mysql_fetch_array($rankResult)) {
$rankArray[] = $row1['username'];
}
Then finding position of that username in the array by using a foreach in php
foreach ($rankArray as $rank => $user) {
if ($user == $username) {
$yourRank = $rank+1;
}
}
It's the long way around, but I suppose it works for what I'm going for.
Was kind of hoping to get it done within the mysql query for efficiency.
Thanks!
You could try grouping to sum the Km as a first query, then follow it by a correlated subquery to find the ranks. For instance, if your values are stored in a table called "test", sum the Km values into a table called testtbl and then do the ranking.
mysql> select * from test;
+------+--------+------+
| Id | km_run | name |
+------+--------+------+
| 1 | 34 | a |
| 3 | 2 | c |
| 1 | 3 | a |
| 4 | 23 | d |
| 3 | 5 | c |
+------+--------+------+
5 rows in set (0.00 sec)
mysql> create table testtbl as
(select Id, sum(km_run) as tot
from test
group by Id);
Query OK, 3 rows affected (0.04 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from testtbl;
+------+------+
| Id | tot |
+------+------+
| 1 | 37 |
| 3 | 7 |
| 4 | 23 |
+------+------+
3 rows in set (0.00 sec)
mysql> select t1.Id,t1.tot,
((select count(distinct t2.tot) from testtbl t2 where t1.tot < t2.tot)+1) as Rk from testtbl t1
order by Rk;
+------+------+------+
| Id | tot | Rk |
+------+------+------+
| 1 | 37 | 1 |
| 4 | 23 | 2 |
| 3 | 7 | 3 |
+------+------+------+
3 rows in set (0.00 sec)

Categories