Distinct entries from the set - mysql

I am using the below query on the above database table but unable to get the distinct value. Help will be appreciated
SELECT DISTINCT doctor_user_id, doctor_name, score, time_in_seconds FROM basket_game_master WHERE game_id='$game_id' ORDER BY score DESC, time_in_seconds ASC LIMIT $limit
The goal is to retrieve the doctor name with unique doctor_user_id who have more score with less time_in_seconds

You can use ROW_NUMBER():
SELECT doctor_user_id, doctor_name, score, time_in_seconds
FROM (SELECT bgm.*,
ROW_NUMBER() OVER (PARTITION BY doctor_user_id ORDER BY score DESC, time_in_seconds ASC) as seqnum
FROM basket_game_master bgm
WHERE game_id = ?
) mgm
WHERE seqnum = 1
ORDER BY score DESC, time_in_seconds ASC
LIMIT ?;
Note the use of ? for the parameters. Do not munge the query string with literal values! That poses a risk for SQL injections and for hard-to-debug syntax errors.

Related

Add second column to order by mysql in a group_concat

I have this query I made based on someone else question here.
SELECT *, FIND_IN_SET( score, ( SELECT GROUP_CONCAT( score ORDER BY score ASC) FROM EventPlayerResult WHERE eventId = 'EventTest0') ) AS position FROM EventPlayerResult WHERE eventId = 'EventTest0' ORDER BY position ASC LIMIT 10
It gives me a leaderboard for the top 10 players. But when I run it, if 2 players has the same score, I need it to filter by another column (energyLeft). So I tried to add , energyLeft DESC inside of my GROUP_CCONCAT but it doesnt change anything. im not familiar with group concat and find in set. So where should I add the logic to order by energyLeft after ordering by score.
I tried something like this :
SELECT *, FIND_IN_SET( score, ( SELECT GROUP_CONCAT( score ORDER BY score ASC, energyLeft DESC) FROM EventPlayerResult WHERE eventId = 'EventTest0') ) AS position FROM EventPlayerResult WHERE eventId = 'EventTest0' ORDER BY position ASC LIMIT 10
You should use the player and not the score inside GROUP_CONCAT() so that the players are ranked by score first and then by energyLeft.
Assuming there is a column like player_id in the table:
SELECT *,
FIND_IN_SET(
player_id,
(
SELECT GROUP_CONCAT(player_id ORDER BY score ASC, energyLeft DESC) FROM EventPlayerResult WHERE eventId = 'EventTest0'
)
) AS position
FROM EventPlayerResult
WHERE eventId = 'EventTest0'
ORDER BY position ASC LIMIT 10;

How can I RANK from AVG sql?

I'm having trouble retrieving the rankings from a single line that has some uuid from that:
SELECT uuid , AVG(nodebuff+debuff+archer+builduhc+uhc+gapple)/6 as Average
from elo_ranked group by uuid
order by AVG(nodebuff+debuff+archer+builduhc+uhc+gapple)/6 desc
limit 3
I specify that the above function works and has the expected result.
Is this what you want?
SELECT uuid, AVG(nodebuff+debuff+archer+builduhc+uhc+gapple)/6 as Average ,
RANK() OVER (ORDER BY AVG(nodebuff+debuff+archer+builduhc+uhc+gapple)/6 DESC) as ranking
FROM elo_ranked
GROUP BY uuid
ORDER BY AVG(nodebuff+debuff+archer+builduhc+uhc+gapple)/6 desc
LIMIT 3;
EDIT:
To rank a specific user, use a subquery:
SELECT u.*
FROM (SELECT uuid, AVG(nodebuff+debuff+archer+builduhc+uhc+gapple)/6 as Average ,
RANK() OVER (ORDER BY AVG(nodebuff+debuff+archer+builduhc+uhc+gapple)/6 DESC) as ranking
FROM elo_ranked
GROUP BY uuid
) u
WHERE uuid = ?;
Also, I'm not sure if you need the aggregation. That would only be needed if a user had multiple rows in the elo_ranked table. If not needed, then you should use:
SELECT u.*
FROM (SELECT uuid, (nodebuff+debuff+archer+builduhc+uhc+gapple)/6 as Average ,
RANK() OVER (ORDER BY (nodebuff+debuff+archer+builduhc+uhc+gapple)/6 DESC) as ranking
FROM elo_ranked
) u
WHERE uuid = ?;
The GROUP BY has a lot of overhead, so this should be faster (unless MySQL has sophisticated optimizations to avoid the aggregation when grouping by a primary key).

SQL query not returning distinct values

I have a game leaderboard comprised of 500 rows of data and I wrote a script to return that data and have no duplicate scores. However, I am getting duplicate scores returned to me. Here is my script.
SELECT DISTINCT
username, score,
FIND_IN_SET(score, (SELECT DISTINCT GROUP_CONCAT(score ORDER BY score DESC)
FROM TPS_STATS)) AS rank
FROM
TPS_STATS
ORDER BY
rank ASC
LIMIT 100;
An example of the duplicate results I am seeing is posted as an image.
If your version of MySql is 8.0 then you can use row_number():
SELECT
username,
score,
row_number() OVER (ORDER BY score desc, username) rn
FROM TPS_STATS
ORDER BY score desc, username
LIMIT 100
See the demo.
If it is lower:
select
username,
score,
(select count(*) from TPS_STATS where score > t.score) +
(select count(*) from TPS_STATS where score = t.score and username < t.username) + 1
rank
from TPS_STATS t
order by rank, username
limit 100
See the demo

how to find index ( id ) of generic column in mysql

I have a table with name rating as this.
I am writing the query like this
SELECT user_id, sum(score) as score
FROM quiz_rashad.rating
group by user_id
order by score desc
then how I get rating index of the 12th user?
Thank you for helping.
Assuming, that "the 12th user" means the user with the ID 12:
In MySQL 8.0+ you can use dense_rank().
SELECT x.rating_index
FROM (SELECT r.user_id,
dense_rank() OVER (ORDER BY sum(r.score) DESC) rating_index
FROM quiz_rashad.rating r
GROUP BY r.user_id) x
WHERE x.user_id = 12;
Edit:
For MySQL 5.7 you have to use subqueries getting the distinct count of total scores greater than or equal the total score for the user with ID 12.
SELECT count(DISTINCT x.score) rating_index
FROM (SELECT r.user_id,
sum(r.score) score
FROM quiz_rashad.rating r
GROUP BY r.user_id) x
WHERE x.score >= (SELECT sum(r.score)
FROM quiz_rashad.rating r
WHERE r.user_id = 12)
We can try using LIMIT with OFFSET here:
SELECT user_id, SUM(score) AS score
FROM quiz_rashad.rating
GROUP BY user_id
ORDER BY score DESC
LIMIT 1 OFFSET 11;
This answer assumes that what you really want here is the record with the twelfth rank. It also assumes that no two users would be tied for the same score.

How to write sql query to get items from range

I would like to get values without the smallest and the biggest ones, so without entry with 2 and 29 in column NumberOfRepeating.
My query is:
SELECT Note, COUNT(*) as 'NumberOfRepeating'
WHERE COUNT(*) <> MAX(COUNT(*))AND COUNT(*) <> MIN(COUNT(*))
FROM Note GROUP BY Note;
SELECT Note, COUNT(*) as 'NumberOfRepeating'
FROM Notes
GROUP BY Note
HAVING count(*) <
(
SELECT max(t.maxi)
FROM (select
Note, COUNT(Note) maxi FROM Notes
GROUP BY Note
) as t
)
AND
count(*) >
(
SELECT min(t.min)
FROM (select
Note, COUNT(Note) min FROM Notes
GROUP BY Note
) as t
)
try this code.
One method would use order by and limit, twice:
select t.*
from (select t.*
from t
order by NumberOfRepeating asc
limit 99999999 offset 1
) t
order by NumberOfRepeating desc
limit 99999999 offset 1;
Try this code,
Select * from Note where NumberOfRepeating < (select MAX(NumberOfRepeating) from Note ) AND NumberOfRepeating > (select MIN(NumberOfRepeating) from Note );
Here in the code, as in your table Note is the name of the table, and NumberOfRepeating is the column name, as in your table.
Try this. It should work
SELECT *
FROM ( SELECT Note, COUNT(*) as 'NumberOfRepeating'
FROM Notes
GROUP BY Note
ORDER BY NumberOfRepeating DESC
LIMIT 1, 2147483647
) T1
ORDER BY T1.NumberOfRepeating
LIMIT 1, 2147483647