sql count and order - mysql

I have a database and two commands to display the same thing
SELECT name, score
FROM sm_easyrank
ORDER BY score DESC, name ASC
LIMIT 0, 10
This selects the players ordered by score, and if two players has the same score, they will be order by name.
SELECT count(*)
FROM sm_easyrank
WHERE score >= (SELECT (score)
FROM sm_easyrank
WHERE steamid = '%s'
)
This will count how many players are before me.
The problem is: I have a position in first order, and another in second (if i have the same score with someone else). I wanna order in second players with same score by name.
sm_easyrank is the table name
score is a column with scores (number column)
steamid is a unique id
name is a column with name of the people
sorry for my english!

If I understand correctly, you can do what you want using a JOIN and conditions that include both the score and name:
SELECT count(*)
FROM sm_easyrank s JOIN
sm_easyrank s2
ON s2.steamid = '%s' AND
(s.score > s2.score OR
s.score = s2.score AND s.name <= s2.name
);

Related

Average maximum MYSQL

I want to select the average of the high score for 2-3 players but im not sure how to go about this.
Table Match has (id, player, score)
I would like to get the maximum score for each specified player (by id) and then calculate the average of these returned scores.
Any help would be appreciated
CREATE TABLE Match(Id integer PRIMARY KEY, score integer);
/* Create few records in this table */
INSERT INTO Match VALUES(1,'10');
INSERT INTO Match VALUES(2,'20');
INSERT INTO Match VALUES(3,'60');
INSERT INTO Match VALUES(4,'100');
INSERT INTO Match VALUES(5,'80');
COMMIT;
select m.*,
(select sum(score)
from (select score
from Match s
where s.id = s.id
order by score desc
limit 3
) s2
) as summax3
from Match m
The following query is going to return the highest score of each player:
SELECT *
FROM
(
SELECT `match`.id, `match`.score
FROM `match`
ORDER BY score DESC
LIMIT 3
) AS high_scores
GROUP BY id
ORDER BY score DESC
And for getting the average:
SELECT AVG(score) AS average
FROM
(
SELECT `match`.id, `match`.score
FROM `match`
ORDER BY score DESC
LIMIT 3
) AS high_scores

Select rank of a specific player sql query

I'm trying to make a query and I already searched for an answer on stackof but didn't find one matching my needs.
I have a table named player in which there are two columns, "nickname" and "score".
I use this query to get the top 5 players:
SELECT nickname, score
FROM player
ORDER BY score DESC LIMIT 5;
and I got this as the answer:
nickname - score:
zod - 30
ciao - 20
jiji - 20
mayina - 20
jon - 0.
Now, I'd like to have the rank of a single player, let's say "jiji" and get 3 as a result, because it's the third result in the list.
I tried many queries like
SELECT COUNT(*) AS rank
FROM player
WHERE score >= (SELECT score FROM player WHERE nickname = 'jiji')
but they always return 4 for "jiji" or "ciao", which is the rank of the last player who gets 20 as score in that table.
How can I get to have 3 for "jiji", instead? Thank you very much.
Try this:
SET #rank=0;
SELECT *
FROM (SELECT #rank:=#rank+1, nickname, score
FROM player
ORDER BY score
DESC) AS t
WHERE t.nickname = 'jiji';
Correct comment about this not being stable in case of score ties. To make it stable, we can change the sorting to be based on score and then nickname:
SELECT *
FROM (SELECT #rank:=#rank+1, nickname, score
FROM player
ORDER BY score, nickname
DESC) AS t
WHERE t.nickname = 'jiji';
Using commonly used definitions, the rank for jiji would be:
SELECT count(*) + 1 AS rank
FROM player
WHERE score > (SELECT score FROM player WHERE nickname = 'jiji');
This returns "2", because there are ties when score = 30.
If you want the rank to be stable and different for each row, you need an additional key. An obvious key (in this case) is nickname:
SELECT count(*) AS rank
FROM player p CROSS JOIN
(SELECT score FROM player WHERE nickname = 'jiji') s
WHERE p.score > s.score or
(p.score = s.score and p.nickname <= 'jiji');

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.

mySQL count and get maximum from table

I have a simple question. I have this table structure http://sqlfiddle.com/#!2/61cee/3/0 and I just want to count score of each player which are attacker and then pick the highest score from all players and his id. I tried this:
SELECT MAX(counts), id_player FROM
(SELECT COUNT(score) AS counts, id_player
FROM fl_poll
WHERE position = 'attacker'
GROUP BY id_player) as maxi
But the result is wrong id. Where I made a mistake? Thanks for advance.
SELECT COUNT(score) AS counts, id_player
FROM fl_poll
WHERE position = 'attacker'
GROUP BY id_player
ORDER BY COUNT(score) desc
LIMIT 1

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