If statement in SQL - mysql

I have a game, and a MySQL database table where I store the results of users. Every result is stored, but on highscore page I show only the best result from a certain user, like this:
SELECT user_id,MAX(score) as score
FROM table
GROUP BY user_id
ORDER BY score DESC LIMIT $startLimit,$numPerPage
But now I also want to make it relate to time it took for player to reach certain score, if the scores are level.
For example if the player has two same scores, I want to grab the one that took him less time (ofcourse there is a column "time" in this table).

Try this:
SELECT user_id,score,MIN(time) as MinTime
FROM
(SELECT user_id,MAX(score) as score,time
FROM table
GROUP BY user_id, time ) T
GROUP BY user_id,score
ORDER BY score DESC
LIMIT $startLimit,$numPerPage
It will return the records with minimum time if the user has same score.

Related

MySQL Fetch highest value by key and then add rank to it

I'm trying to create a mysql query that looks through my scoreboard for a given playerid and then finds their highest score and then adding a rank to that score.
I've come quite close to what I'm trying to achieve with this code:
SELECT PlayerUUID, `iGamescore` as score, FIND_IN_SET( iGamescore, (
SELECT GROUP_CONCAT( iGamescore
ORDER BY iGamescore ASC )
FROM crystm_gameScoreboard )
) AS rank
FROM crystm_gameScoreboard
WHERE PlayerUUID = '4c8984f3-651a-48bc-ad1a-879624380fab'
LIMIT 1
Returns:
But I do know that this player has played multiple times and is therefore multiple times in the scoreboard. As seen here:
So the issue here is that yes, it does find the player and gives the rank correctly.. However, since it exists multiple times, it saves the very first score instead of the highest score. How would I fix my query to correct for this or would you instead of creating a new score every time they create a highscore for themselves, just update their previous record in the scoreboard?
Thanks in advance
To get the highest score you need a GROUP BY:
SELECT
PlayerUUID,
MAX(`iGamescore`) as score
RANK() OVER (ORDER BY MAX(`iGamescore`) DESC) as Rang
FROM crystm_gameScoreboard
GROUP BY PlayerUUID
ORDER BY 3 ASC
The order by 3 ASC makes the list sorted by rank
This post solved it:
MySQL - Rank user amongst list of top high-scores
Had everything I was looking for. I dont know why I could not find this post but when searching, keywords are important haha.
Thanks for inputs tho.

Get row rank without fetching every row

I'm using this query to fetch a highscore of a certain user.
SELECT score FROM highscores WHERE user_id=?
I would like to know the how-many'th this particular highscore is compared to the other scores. So basically the row number after we DESC ordered the highscores table.
I could of course fetch all rows and look at the array key but I was wondering if there's a more performance friendly method directly via the MySQL query. The highscore table contains around 500k rows, and it seems a bit overkill (and it will take some time) to have to fetch them all first just to get the rank number of the user's score.
Some time ago I helped a friend with a similar task, and wrote an article,
How to get a single player's rank based on the score.
So the idea is to run a count(*) query with a WHERE clause to include all players having a higher score:
SELECT count(*)+1 FROM players WHERE score > ?
or, based on the user id,
SELECT count(*)+1 FROM players WHERE score > (SELECT score FROM players WHERE id = ?)
This solution is much simpler than anything I was able to find on Stack Overflow.
It can be also refined, to take into account other fields, in case two users have the same score, such as time when the score has been updated:
SELECT count(*)+1 FROM players WHERE score > ? OR (score = ? AND score_updated < ?)

How to order a sql query for a ranking system with both average and number of votes?

I'm creating a list for best movies which are based on the users votes like imdb. I have done the list with this sql query:
SELECT data_id, COUNT(point), SUM(point)
FROM voting_table
WHERE data_type='1'
GROUP BY data_id
order by SUM(point)/COUNT(point)
DESC limit 100
This works well but i want also the number of votes(point) affect the order. I mean if a movie gets average of 8 with 10 votes and another movie gets average of 8 but with 5 votes. The one which has more votes should be listed higher than the other one. How can i do it? And is the query i wrote is efficent for server performance?
There is function AGV, I suggest you use that.
sort by avg, then by count or sum
...
ORDER BY AVG(point) DESC, COUNT(point) DESC
...
As of performance, there is not much you can do wihout complicating data structure.
It should be fine as it is unless your site si going to be as popular as imdb.
If your voting table grows past the point where speedup is needed then you need to start precalculating stuff (for real time updates using triggers that update score in movies table or some other intermediate table dedicated for that, other methods)
Just add the second order you want separated by comma .try this
SELECT data_id, COUNT(point), SUM(point)
FROM voting_table
WHERE data_type='1'
GROUP BY data_id
order by SUM(point)/COUNT(point) ,COUNT(point)
DESC limit 100
Try changing your order by clause to be:
order by SUM(point)/COUNT(point) desc, COUNT(point) desc
As it stands, your query appears to be efficient.

Ranking entries and group by

I have a website where people are saving highscores in games. I've been trying to assign a rank to a player's highscore by finding the number of other highscores that are higher. So if the query finds 5 people with higher highscores, the player's highscore rank will be 6.
The thing is that more than one score (for the same game) can be recorded in the database for every user. This is why I'm using GROUP BY user when I want to display only a player's best score in a game (not all of his scores in that game).
Here's the code I am using now. It doesn't work, since the query seems to always return 2 (like if it was always returning that there was only one score higher than the player's highscore). If I remove temp GROUP BY user, it returns an half-correct value, since counting all the scores (if a player as multiple scores in a game) from every player in a given game.
$count3 = mysql_result(mysql_query("SELECT COUNT(*) + 1 as Num FROM (SELECT * FROM ava_highscores WHERE game = $id AND leaderboard = $get_leaderboard[leaderboard_id] AND score > '$highscore2[score]') temp GROUP BY user");
When you use GROUP BY then COUNT returns a count of rows per group rather than a single count of all rows in the result set. Use COUNT(DISTINCT ...) instead. Also you don't actually need the inner select. You can write it all as a single query:
SELECT COUNT(DISTINCT `user`) + 1 AS Num
FROM ava_highscores
WHERE game = '3'
AND leaderboard = '5'
AND score > '1000'
Notes
Make sure that your score column is a numeric type (not a varchar type) so that the comparison works correctly.
Adding an index on (game, leaderboard, score) will make the query more efficient. The order of the columns in the index is also important.

mysql max function usage

the table videos has the folowing feels
id,average,name
how can i write the query, to select the name of video, which have the max average!!!
i can do that vith two queries, by selecting the max(avege) from the table, and then find out the name, where ihe average equal to max!!! but i want to do that in one query!!!
help me please!!!
You don't need a group by for this, you just want to select the highest average!
SELECT * FROM videos ORDER BY average DESC LIMIT 1;
You can use an ORDER BY with a LIMIT:
SELECT id, average, name FROM videos ORDER BY average DESC LIMIT 1
ORDER BY average DESC orders the rows in order of descending average (i.e. the first row will have an average equal to MAX(average)). LIMIT 1 causes only the first row to be returned.
SELECT id,name,MAX(average) FROM videos;
All fields you choose to SELECT will be returned. Getting more data back is just a case of SELECTing more fields.