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.
Related
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
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
The following code works for what I am looking for but I am trying to see if there is a better way to create an efficient news feed. This news feed is supposed to choose the most recent comments and/or likes, etc but only exhibit the most recent per user (i.e. if John liked 2 items and commented on 3 items, only show the most recent comment and like. Please note that there are multiple UNIONs involved.
SELECT *
FROM (SELECT username, time, comment FROM comments ORDER BY time DESC) AS temp
GROUP by username
UNION
SELECT *
FROM (SELECT username, time, likes FROM likes ORDER BY time DESC) AS temp
GROUP BY username
ORDER BY time DESC
LIMIT 10
I think you can JOIN the two tables on username, but this will give you extra columns instead of the union, something like:
SELECT
c1.username,
c1.`time` AS CommentTime,
c1.comment,
l1.`time` AS LikeTime,
l1.likes
FROM comments AS c1
INNER JOIN
(
SELECT username, MAX(`time`) LatestTime
FROM Comments
GROUP BY username
) AS c2 ON c1.username = c2.username
AND c1.`time` = c2.LatestTime
INNER JOIN Likes l1 ON c1.username = l2.username
INNER JOIN
(
SELECT username, MAX(`time`) LatestTime
FROM Likes
GROUP BY username
) AS l2 ON l1.username = l2.username
AND l1.`time` = l2.latestTime
ORDER BY c1.`time` DESC
LIMIT 10;
This will give you the username with the latest comment and the latest likes with the latest time.
I have a table called users which looks like:
-id
-email
-login
-admin
-coins
-cash
-premium
-IP
-pass
-ref
-signup
-online
-promote
-activate
-banned
-rec_hash
-country
-c_changes
-sex
-daily_bonus
If say user with id 81 referred 10 people then those 10 people would have "81" in their ref column.
I would like to create a top 5 referral table but I'm having trouble with the query and displaying that in PHP, would anybody be able to help?
I FORGOT TO MENTION IF THEY HAVE NO REFERRAL IT SHOWS AS 0 HOW WOULD I EXCLUDE 0 FROM BEING SHOWN AS A REFERRAL?
You can do it in a single SQL statement like this:
SELECT ref, COUNT(*) AS num FROM users
GROUP BY ref ORDER BY num DESC LIMIT 5
But that will just get you the 5 IDs, rather than their user rows. You can then perform a further query to get the actual rows. Alternatively, use the above query with a join to do it all in one.
IF THEY HAVE NO REFERRAL IT SHOWS AS 0
messy design - this should be null. Regardless...
SELECT u.login, ilv.referred
FROM
(SELECT ref, COUNT(*) AS referred
FROM users
WHERE ref IS NOT NULL
AND ref>0
GROUP BY ref
ORDER BY COUNT(*) DESC
LIMIT 0,5) ilv
INNER JOIN users u
ON ilv.ref=users.id
ORDER BY ilv.referred DESC;
Or and SQL like this:
SELECT u.*, COUNT(*) as referrers FROM users r JOIN users u ON r.ref = u.id
GROUP BY u.id ORDER BY referrers DESC LIMIT 5
It is faster to use just one statement even with a join on the same table.
I'm building a website with points system, similar to Stackoverflow;
This is the code I'm using to display top users (for all time):
SELECT id, username, active, points
FROM users
WHERE active='1'
ORDER BY points DESC
But how can I show the top users in 24 hours (also points)?
You would have to make a special table that would record when (and how many) points the user received.
EDIT
E.g. table points
user_id time awarded_points
-------------------------------------
1 1298745681 10
...
Then you just ask for the points awarded today with WHERE time > UNIX_TIMESTAMP(CURDATE()) or in the last 24 hours WHERE time > UNIX_TIMESTAMP()-24*3600.
Example use:
SELECT u.id, u.username, u.active, SUM(p.awarded_points) AS points
FROM points AS p
LEFT JOIN users AS u ON u.id = p.user_id
WHERE time > UNIX_TIMESTAMP(CURDATE())
AND u.active = '1'
GROUP BY p.user_id
ORDER BY points DESC
I'd also suggest adding a LIMIT to the query, especially if your site grows big.
Your need another table, where all users activites/points would be write
And than join with this table, and condition to 24h
Add a table recording the points each user receives and when with a foreign key relation to the users table
For example a table named points with the following columns
userid (FK to users table)
datetimeallocated
numberofpoints
other columns of interest e.g. user who allocated the points etc
You then need to query this table e.g.
SELECT SUM(numberofpoints), userid
FROM points
WHERE datetimeallocated >= DATE_SUB(CURDATE(), INTERVAL 1 DAY)
GROUP BY userid
ORDER BY SUM(numberofpoints) DESC