how to get position rank of specific row using just mysql query? - php

I have table Users which contains columns: id, name, points, extra_points.
How can I get position rank for specific user, when the rank is sum of points and extra_points?
For all users list rank Im using this query: "SELECT id, (points + extra_points) AS total FROM users ORDER BY total desc"; and the while loop with html ol tag (so there is position number).
But I dont know how to show the rank for a sinlge user (in user profile page)?
Any help will be great.

SELECT users1.id, (users1.points+users1.extra_points) AS total, COUNT(*)+1 AS rank
FROM users users1
INNER JOIN users users2 ON users1.points+users1.extra_points < users2.points+users2.extra_points
WHERE users1.id = $id

Well, for a single user, you'd change the select query so it looks like
"SELECT (points + extra_points) AS total FROM users WHERE id = $id LIMIT 1"
Need to specify which user as a WHERE clause. Also, since you presumably know the id already, don't need to select it, and since it's just one user, don't need the ORDER BY either. And LIMIT 1 will stop it from checking the rest of the rows once it's found it.

this isn't tested, but i hope you can understand whats my idea - simply use a subselect to count all users with more points:
SELECT
id,
(points + extra_points) AS total,
(SELECT COUNT(*) FROM users WHERE (points + extra_points)) >= (u.points + u.extra_points) AS rank
FROM
users u
WHERE
id = ?;

Here's the answer if you have a ClientID and Points column in a table called Client:
<CFQUERY DATASOURCE="YourDatasource" name="YourQueryName">
SELECT ClientID, (Pts) AS total,
(SELECT COUNT(*) FROM Client
WHERE (Pts) >= (u.Pts)) AS rank
FROM Client u
WHERE ClientID = CLIENTID_OF_YOUR_CHOICE_HERE;
</CFQUERY>

Related

Add up column using while not breaking other code

My connect to my database works fine so I will include just the code. What I am trying to do is create a sum of the total hours spent on a specific project. The code I have right now displays the comments all the comments from the last day the project was updated:
$query = "SELECT id, date,(select username from users where id = u.user_id) as user, (select description from requests where id = u.request_id) as request, notes, hours from updates u where u.request_id=$rid and date(date) = (select max(date(date)) from updates where request_id = $rid) order by (select description from requests where id = u.request_id) asc";
This is how it is displayed on the web page:
Click to see image of what is displayed on web page
The "test" code that I have that will add the total hours:
$query = "SELECT id, date,(select username from users where id = u.user_id) as user, (select description from requests where id = u.request_id) as request, notes, SUM(hours) as clienthours, hours from updates u where u.request_id=$rid and date(date) = (select max(date(date)) from updates where request_id = $rid) order by (select description from requests where id = u.request_id) asc
This is how it is display on the web page. Notice that all the other comments are gone except the first one of the day.
Click to see image of what is display on web page
I tried adjusting the order of the query but it will send me errors and break the code. I haven't been able to find a solution and would appreciate any help I can get. I am not very advanced when it comes to PHP so my methods are odd and I am building off of someone else code. Any advice will help!
Thank you.
I'd suggest that the main issue with your second script is that you are trying to SUM a column which is returning one row, in SQL you can only return a SUM() when it is the only column in your SELECT.
The below should get around this and also will be more efficient for you by using joins (I've made the assumption that updates.request_id is the unique primary key)
SELECT up.id, up.date, us.username, description, notes,
(SELECT SUM(Hours) FROM updates z WHERE z.request_id = up.request_id)
FROM updates up
INNER JOIN requests r ON u.request_id = r.id
INNER JOIN users us ON up.user_id = us.id
WHERE up.request_id = $rid AND
up.date = (SELECT MAX(date) FROM updates WHERE request_id = $rid)
ORDER BY r.description ASC;

SQL statement for getting user rank in proper order?

I am looking for an SQL statement that returns users rank by score, but does so in order, which is not happening with the code below:
$sql = "SELECT COUNT(*) AS rank FROM users WHERE points>=(SELECT points FROM users WHERE uid='$uid')";
Instead, each user has the same rank depending on how many users there are. So if there are 25 users, each of their ranks will display as 25 but this is not actually the case, as surely there must be an individual rank for each user.
I have tried a couple of different of different solutions, but I can't quite put the logic together. I thought this would work:
$sql ="SELECT COUNT(*)-1 AS rank FROM users WHERE points>=(SELECT points FROM users WHERE uid='$uid' ORDER BY DESC)";
But I've had no success.
TLDR; How could I change my SQL statement to reflect users rank in order by score, without multiple users having the same rank?
If you are trying to order the data in the table using the points and give them individual rank you can use ROW_NUMBER()
SELECT *,ROW_NUMBER() OVER (ORDER BY points DESC) AS RANK FROM users
ROW_NUMBER() is not available in MYSQL. You can do following for MYSQL
SELECT
#r:=#r+1 Rank,tbl.*
FROM users tbl, (select #r:=0) as r
ORDER BY users.points DESC;
Consider you have data
Points
3
7
8
Using Select statement with ROW_NUMBER() you will get result as follows
Result:
Points Rank
8 1
7 2
3 3

Mysql - How to get a row number after Order by?

Let's say I have a table with the following columns:
p_id
userid
points
Let's say these columns have over 5000 records. So we actually have users with points. Each user has an unique row for their point record. Imagine that every user can get points on the website by clicking somewhere. When they click I update the database with the points they get.
So we have a table with over 5000 records of people who have points, right? Now I would like to order them by their points (descending), so the user with the most point will be at the top of the page if I run a MySQL query.
I could do that by simply running a query like this:
SELECT `p_id` FROM `point_table` ORDER BY `points` DESC
This query would give me all the records in a descending order by points.
Okay, here my problem comes, now (when it is ordered) I would like to display each user which place are they actually. So I'd like to give each user something like this: "You are 623 of 5374 users". The problem is that I cannot specify that "623" number.
I would like to run a query which is order the table by points it should "search" or count the row number, where their records are and than return that value to me.
Can anyone help me how to build a query for this? It would be a really big help. Thank you.
This answer should work for you:
SET #rank=0;
SELECT #rank:=#rank+1 AS rank, p_id FROM point_table ORDER BY points DESC;
Update: You might also want to consider to calculate the rank when updating the points and saving it to an additional column in the same table. That way you can also select a single user and know his rank. It depends on your use cases what makes more sense and performs better.
Update: The final solution we worked out in the comments looked like this:
SELECT
rank, p_id
FROM
(SELECT
#rank:=#rank+1 AS rank, p_id, userid
FROM
point_table, (SELECT #rank := 0) r
ORDER BY points DESC
) t
WHERE userid = intval($sessionuserid);
Row number after order by
SELECT ( #rank:=#rank + 1) AS rank, m.* from
(
SELECT a.p_id, a.userid
FROM (SELECT #rank := 0) r, point_table a
ORDER BY a.points DESC
) m
For some reason the accepted answer doesn't work for me properly - it completely ignores "ORDER BY" statement, sorting by id (primary key)
What I did instead is:
SET #rn=0;
CREATE TEMPORARY TABLE tmp SELECT * FROM point_table ORDER BY points DESC;
SELECT #rn:=#rn+1 AS rank, tmp.* FROM tmp;
Add a new column for position to the table. Run a cron job regularly which gets all the table rows ordered by points and then update the table with the positions in a while loop.

MYSQL position of row by order

I have had a look through google results, but can't find a simple answer, I have a table
id, points (and more fields, but they dont affect anything)
How would I go about Getting position of record 24(id) ordered by points DESC?
I'm not sure I've understood your question
select * from table order by points desc limit 23,1
Select Count(*) from (
Select ID from UnNamedTable A where A.points>(Select B.Points from UnNamedTable B where B.ID=24)
)
Are you trying to figure out out what place a user is in based on a points system?
If so then just find how many users have more points than a particular user then add 1.
SELECT COUNT(*) + 1 AS 'position' FROM table WHERE points >
( SELECT points FROM table WHERE id = someIDhere )
You could create a variable to keep track of your row position after sorting. Something like this would work:
select #rownum:=#rownum+1 ‘rank’, p.* from table1 p, (SELECT #rownum:=0) ID order by Points desc limit 10;

How to form an optimal query to get high scores from a data base?

I'm using a MySQL database to store scores for my game. A very simplified version of the table would be
(PlayerID - int)
(Name - string)
(Score - int)
I'd like to form a query that would return me a set of say 10 results where the player of interest is in the middle of the table.
Perhaps an example would make it more clear.
I have just achieved a high score, my name is Steve. When I look at the high score table I'd like to see the 5 scores below me and the 5 scores above me. Obviously if I have the top score I will see the 9 scores below me, and conversely, if I am at the bottom I will see the 9 scores above me. The score table could consist of thousands of scores.
As the database is specifically designed for querying sets of data I'd like to reduce the amount of post processing on the results.
Does anyone have an idea for a query to achieve this?
Thanks
Rich
if you have the user id and score (userId and userScore) you can do:
SELECT * FROM Scores
WHERE PlayerID = userId
OR PlayerID IN (SELECT PlayerID FROM Scores WHERE Score > userScore ORDER BY Score LIMIT 5)
OR PlayerID IN (SELECT PlayerID FROM Scores WHERE Score < userScore ORDER BY Score DESC LIMIT 5)
ORDER BY Score
EDIT: following your comments:
First of all, you need to know the rank of the current user. You can know it with such a query as SELECT COUNT(*) FROM Scores WHERE Score > userScore
It gives you a number n
Then you compute two numbers usersUp and usersDown such as usersDown + userUp = 10 and n - userUp>0 and n + usersDown < SELECT COUNT(*) FROM Scores
Then you can use a UNION instead of IN and Subqueries:
SELECT * FROM Scores WHERE PlayerID = userId
UNION
SELECT * FROM Scores WHERE Score > userScore ORDER BY Score LIMIT usersUp
UNION
(SELECT * FROM Scores WHERE Score < userScore ORDER BY Score LIMIT usersDown)
if you want to stay on the mysql server side you can gather all that in a stored procedure

Categories