MySQL userscore per round - mysql

Currently I'm struggling with a MySQL query. I want to calculate the score for a user per round. I'm trying to get the user that has the best score for a certain round.
My current result:
SELECT user_id, SUM(result_points), round_id
FROM result
GROUP by user_id, round_id
ORDER by round_id ASC, MAX(result_points) DESC
Query result:
Seems to be fine, thing is: I only need the user with the highest score per round.
Like this:
Do you have any idea how to accomplish this with the given query?

You'll want to use the query that you have as a subquery along with the MAX function on the total points per round that you are getting from your query.
SELECT user_id, MAX(roundResults.points) as points, round_id
FROM (SELECT user_id, SUM(result_points) as points, round_id
FROM result
GROUP by user_id, round_id
ORDER by round_id, points DESC) AS roundResults
GROUP by round_id
See the fiddle here.
Note: ORDER BY points DESC preserves the user_id placement.

Your query should be
SELECT user_id, MAX(result_points), round_id
FROM result
GROUP by user_id, round_id
ORDER by round_id

I don't know if you're using a SUM() because there can be diferent result_points for the same user_id and round_id. If that's not the case, you could try:
SELECT result.user_id, result.result_points, result.round_id
FROM result
JOIN (
SELECT b.round_id, MAX(b.result_points) AS max_result_points
FROM result b
GROUP BY b.round_id
) a ON result.round_id = a.round_id AND result.result_points = a.max_result_points
ORDER BY result.round_id

Related

sql return most prevalent column value

I'm a beginner at SQL, how do I get a query which returns the most prevalent column value? Probably there is an answer somewhere but I don't know how to google it.
For example in the user_id column the query should return the value 1 because this is the most prevalent number.
One approach is to do a GROUP BY aggregation and then apply a LIMIT trick:
SELECT user_id, COUNT(*) AS cnt
FROM yourTable
GROUP BY user_id
ORDER BY COUNT(*) DESC
LIMIT 1;
If you want something more complex, then you would be getting into the realm of rank functionality. MySQL (at least as of the current release) does not support built-in rank support, so it can be tricky to perform such queries.
SELECT top 1 user_id, COUNT(*) AS cnt
FROM yourTable
GROUP BY user_id
ORDER BY COUNT(*) DESC
Have a common table expression that counts each user_id. Select user_id where the count is the max count. Will return both user_id's in case of a tie.
with cte as
(
SELECT user_id, COUNT(*) AS cnt
FROM yourTable
GROUP BY user_id
)
select user_id
from cte
where cnt = (select max(cnt) from cte)

how to check if there exists 2nd highest score in SQL?

I have a table which has a int column representing for scores of student. I want to select the 2nd highest score if there does exists for 2nd highest score, and if not, return null. Wondering how to implement in SQL.
I am using MySQL/SQL Workbench.
This query would return the second highest value if present or-else NULL
SELECT MAX(score)
FROM table_name
WHERE score<>(
SELECT MAX(score)
FROM table_name);
Please try executing following sql query for retrieving 2nd highest score
SELECT score from table order by score desc limit 1,1
The above query will return 2nd highest score if it exists or NULL if it the record does not exists
When there is top 2 highest scores then the second one will be displayed
other wise ie: if it has single maximum value overall the table then it displays null..
select top 1 case when row_number() over (order by tbl.score asc) =2 then a else null end ,row_number() over (order by tbl.score asc) as ranks from (
select top 2 score from table group by score order by 1 desc
)tbl
order by 1 desc
I have selected top two records of desc then taking second record..
If it is not present then it will displays null
Try following query
SELECT max(score) FROM table WHERE score NOT IN (SELECT max(score) FROM table);
OR
SELECT max(score) FROM table WHERE score < (SELECT max(score) FROM table);
I was thinking about this on how to display the nth highest value not only the 2nd. We could use the min code instead of the max.
Select * from employee where salary= (Select min(salary) from (select * from employee order by salary desc limit 2) as MyTop);
this can modified for any nth highest value wanted by only changing the desc limit to the "nth" needed.

MySQL ranking feature

I am trying to create a ranking system using the data in my table. It has 2 columns, name and score. One user can have multiple scores. This is what I have so far:
("SELECT name, score, FIND_IN_SET( score, (SELECT GROUP_CONCAT ( score ORDER BY score DESC ) FROM data )) AS rank FROM scores");
But this command lists all the user's previous scores when I only need the highest score.
Does anyone know how I can achieve this?
Try
SELECT name, sum(score) from scores group by name order by sum(score) desc limit 1
And if you don't want to sum then use
SELECT name, max(score) from scores
The below query will pop the list of name in the order of highest score respectively.
select name, max(score) as score from scores group by name order by score desc
You can use SELECT DISTINCT name, score ...
and Select TOP 1 and ORDER BY

Select sum of top three scores for each user

I am having trouble writing a query for the following problem. I have tried some existing queries but cannot get the results I need.
I have a results table like this:
userid score timestamp
1 50 5000
1 100 5000
1 400 5000
1 500 5000
2 100 5000
3 1000 4000
The expected output of the query is like this:
userid score
3 1000
1 1000
2 100
I want to select a top list where I have n best scores summed for each user and if there is a draw the user with the lowest timestamp is highest. I really tried to look at all old posts but could not find one that helped me.
Here is what I have tried:
SELECT sum(score) FROM (
SELECT score
FROM results
WHERE userid=1 ORDER BY score DESC LIMIT 3
) as subquery
This gives me the results for one user, but I would like to have one query that fetches all in order.
This is a pretty typical greatest-n-per-group problem. When I see those, I usually use a correlated subquery like this:
SELECT *
FROM myTable m
WHERE(
SELECT COUNT(*)
FROM myTable mT
WHERE mT.userId = m.userId AND mT.score >= m.score) <= 3;
This is not the whole solution, as it only gives you the top three scores for each user in its own row. To get the total, you can use SUM() wrapped around that subquery like this:
SELECT userId, SUM(score) AS totalScore
FROM(
SELECT userId, score
FROM myTable m
WHERE(
SELECT COUNT(*)
FROM myTable mT
WHERE mT.userId = m.userId AND mT.score >= m.score) <= 3) tmp
GROUP BY userId;
Here is an SQL Fiddle example.
EDIT
Regarding the ordering (which I forgot the first time through), you can just order by totalScore in descending order, and then by MIN(timestamp) in ascending order so that users with the lowest timestamp appears first in the list. Here is the updated query:
SELECT userId, SUM(score) AS totalScore
FROM(
SELECT userId, score, timeCol
FROM myTable m
WHERE(
SELECT COUNT(*)
FROM myTable mT
WHERE mT.userId = m.userId AND mT.score >= m.score) <= 3) tmp
GROUP BY userId
ORDER BY totalScore DESC, MIN(timeCol) ASC;
and here is an updated Fiddle link.
EDIT 2
As JPW pointed out in the comments, this query will not work if the user has the same score for multiple questions. To settle this, you can add an additional condition inside the subquery to order the users three rows by timestamp as well, like this:
SELECT userId, SUM(score) AS totalScore
FROM(
SELECT userId, score, timeCol
FROM myTable m
WHERE(
SELECT COUNT(*)
FROM myTable mT
WHERE mT.userId = m.userId AND mT.score >= m.score
AND mT.timeCol <= m.timeCol) <= 3) tmp
GROUP BY userId
ORDER BY totalScore DESC, MIN(timeCol) ASC;
I am still working on a solution to find out how to handle the scenario where the userid, score, and timestamp are all the same. In that case, you will have to find another tiebreaker. Perhaps you have a primary key column, and you can choose to take a higher/lower primary key?
Query for selecting top three scores from table.
SELECT score FROM result
GROUP BY id
ORDER BY score DESC
LIMIT 3;
Can you please try this?
SELECT score FROM result GROUP BY id ORDER BY score DESC, timestamp ASC LIMIT 3;
if 2 users have same score then it will set order depends on time.
You can use a subquery
SELECT r.userid,
( SELECT sum(r2.score)
FROM results r2
WHERE r2.userid = r.userid
ORDER BY score DESC
LIMIT 3
) as sub
FROM result r
GROUP BY r.userid
ORDER BY sub desc
You should do it like this
SELECT SUM(score) as total, min(timestamp) as first, userid FROM scores
GROUP BY userid
ORDER BY total DESC, first ASC
This is way more efficient than sub queries. If you want to extract more fields than userid, then you need to add them to the group by.
This will of cause not limit the number of scores pr user, which indeed seems to require a subquery to solve.

Selecting values grouped to a specific identifer

I have an application that tracks high scores in a game.
I have a user_scores table that maps a user_id to a score.
I need to return the 5 highest scores, but only 1 high score for any specific user.
So if user X has the 5 highest scores on a purely numerical basis, I simply return the highest one and then the next 4 user scores.
I have tried to use:
SELECT user_id, score
FROM user_scores
ORDER BY score DESC
GROUP BY user_id
LIMIT 5
But it seems that MySQL drops any user_id with more than 1 score.
This should work:
SELECT user_id, MAX(score)
FROM user_scores
GROUP BY user_id
ORDER BY MAX(score) DESC
LIMIT 5
SELECT user_id, MAX(score) AS score
FROM user_scores
GROUP BY user_id
ORDER BY score DESC
LIMIT 5
Should do the job for you... though don't forget to create indexes...
You can't group by without a summary-function (SUM, COUNT, etc.)
The GROUP BY clause says how to group the SUMs or COUNTs.
If you simply want to break the long list into bunches with a common value, that's not SQL. That's what your application has to do.
Can you use the Distinct operator to say
SELECT DISTINCT(user_id), score
FROM user_scores
ORDER BY score DESC
LIMIT 5
didn't test so not sure if that will definitely work
Returning only the maximum score for a given user is something like the following.
SELECT user_id, max(score) FROM user_scores
GROUP BY user_id
I don't know whether it was a lack of caffeine or just brain explosion, but the answers here were so easy.
I actually got it working with this monstrosity:
SELECT s1.user_id,
(SELECT score FROM user_scores s2 WHERE s2.user_id = s1.user_id ORDER BY score DESC LIMIT 1) AS score
FROM user_scores s1
GROUP BY s1.user_id
ORDER BY s1.score DESC
LIMIT 5