Join multiple tables and order by sum of row - php

Recently began working on a matchmaking system, where in this system there are 2 tables. One table is for matches and one table is for ranks.
The table for ranks starts off like this
table_ranks:
date
playeruid
rank
table_matches:
date
playeruid
playerpoints
I'm trying to now order the player by their points. However, in order to do this, I have made a query:
SELECT * FROM table_ranks ORDER by rank DESC
But now what I realize, is that I need to add the playerpoints on top of the rank. So basically, I need to add playerpoints to the player's current ranking. So, if I had this for an example row:
table_ranks:
2/20/15
Player1
56
table_matches:
2/27/15
Player1
5
I would need to build a query that takes the 56 of player1, looks for player1 in the matches and anywhere it sees it, it would need to add his 5 points making it a sum of 56. Once this is determined it would ORDER by this value in order to determine who is ranked with what. How do I begin my query? I understand that in order to join the tables, I need to start off like this:
"SELECT table_ranks., table_matches. from table_ranks, table_matches ORDER by RANK..."
Then to finish it,I would have to take the current value of the rank, then grab the specific player it's referring to and take all the matches and add up all the playerpoints to his rank then to determine how to order it by.

Try this:
SELECT r.playeruid, r.date AS rank_date, m.date AS macthes_date,
(r.rank + m.playerpoints) AS total_points
FROM table_ranks r INNER JOIN table_matches m ON r.playeruid = m.playeruid
ORDER BY total_points DESC
This query assumes that playeruid is unique in both tables.

Try the following query. I tested on a similartable structure and it should work
SELECT * , playeruid AS player_id, (
SELECT SUM( playerpoints )
FROM `table_matches`
WHERE playeruid = player_id
) AS points
FROM table_ranks
ORDER BY points DESC

Related

Getting ordered rows partly

Hello developers out there,
I want to create a ranking list in my program, and for that want to get the users of the mysql database ordered by their points. I'm doing this with:
select `name`,`points` from users order by `points` desc
For better performance i don't want to get all users but just 10+ and 10- from a given user, because i don't want to show the whole ranking list in the program anyways. Could somebody help me with this?
One method uses subqueries and union all:
(select name, points
from users
where points <= (select u2.points from users u2 where u2.name = ?)
order by points desc
limit 11
) union all
(select name, points
from users
where points > (select u2.points from users u2 where u2.name = ?)
order by points asc
limit 10
) ;
This returns 21 rows, with the specified user included.

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 select statement - How to calculate the current ranking

I have a table called user_rankings where votes (voted) are stored for each user. I want to display the current ranking of users (this week) that depends on how much votes the user got.
example to clarify:
RANK-NR, USERNAME, VOTED,
1, name1, 18 times
2, name1, 16 times
(my ranking here), myname, 13 times
In this example my ranking should be 3. If I'd have 17 votes, I would be number 2. If there would be five users above me, I would be number 8. I guess you get the point.
Now I can display the ranking number easily with an incrementing $i in PHP. But I only want to show a list limited to ten users (a top ten list) and directly after that my current ranking, if I'm not already in that top ten list. So I'm just wondering how to get my exact ranking number using MySQL.
I'm assuming to have hundreds of users in this list with a different amount of votes.
This is my statement at the moment:
SELECT
`voted`
FROM `users_ranking`
WHERE
`uid`='".$_SESSION['uid']."'
AND
WEEKOFYEAR(`date`)=WEEKOFYEAR(NOW())
LIMIT 1
I can't give you the exact code, but i think the following can give you some idea
select 'RANK-NR', 'USERNAME', 'VOTED' from
(
select 'RANK-NR', 'USERNAME', 'VOTED', rank() over (order by 'voted' desc) as rank
from users_ranking
where
uid='".$_SESSION['uid']."'
AND
WEEKOFYEAR(date)=WEEKOFYEAR(NOW())
) as abc
where
rank<11
i think rank() over (order by<>) should work
I just found out myself that this solution works:
SELECT *
FROM
(
SELECT #ranking:= #ranking + 1 rank,
a.`uid`
FROM `users_ranking` a, (SELECT #ranking := 0) b
ORDER BY a.`votes` DESC
) s
WHERE `uid`='".$_SESSION['uid']."'
AND
WEEKOFYEAR(`date`)=WEEKOFYEAR(NOW())
LIMIT 1
OK, example to go with my comment. What you have will often work, but there is nothing to force MySQL to do the sort before it applies the ranking.
As such using an extra level of sub query would give you this (not tested). The inner sub query is getting all the user ids for the relevant week in the right order, while the next outer sub query applies the ranking to this ordered result set. The outer query just gets the single returned row you require.
SELECT c.rank, c.uid
FROM
(
SELECT #ranking:= #ranking + 1 rank, a.uid
FROM
(
SELECT uid, votes
FROM `users_ranking`
WHERE WEEKOFYEAR(`date`) = WEEKOFYEAR(NOW())
ORDER BY votes DESC
) a,
(SELECT #ranking := 0) b
) c
WHERE c.uid = '".$_SESSION['uid']."'
LIMIT 1
Another possibility avoiding the sub query and also avoiding the need for a variable is to do a join. This is (mis)using HAVING to slim down the result to the single row you are interested in. Down side of this solution is that if multiple users have the same score they will each get the same ranking.
SELECT b.uid, COUNT(a.uid)
FROM users_ranking a
LEFT OUTER JOIN users_ranking b
ON WEEKOFYEAR(a.`date`) = WEEKOFYEAR(b.`date`)
AND a.votes >= b.votes
GROUP BY b.uid
HAVING b.uid = '".$_SESSION['uid']."'
EDIT
To give the top 10 rankings:-
SELECT b.uid, COUNT(a.uid) AS rank
FROM users_ranking a
LEFT OUTER JOIN users_ranking b
ON WEEKOFYEAR(a.`date`) = WEEKOFYEAR(b.`date`)
AND a.votes >= b.votes
GROUP BY b.uid
ORDER BY rank
LIMIT 10
Although in this case it might be quicker to use a sub query. You could then put the LIMIT clause in the sub query with the ORDER BY, hence it would only need to use the variables to add a rank to 10 rows.
I am not sure how to combine that with the query for a single user, mainly as I am not sure how you want to merge the 2 results together.

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;

Categories