简体   繁体   中英

SQL query not ordering right

i have a test where people submit it and then the seconds they used to complete the test is also submitted.

This is the query:

SELECT *
FROM namethatchampion_stats
GROUP BY user
ORDER BY seconds ASC
LIMIT 100

This is the table structure:

id | user | seconds | time

I want my users to be able to submit the test many times but this only lists the first time he submitted. So if the user gets a better time the seconds time he posts it will not use that row in the database, it will only use the first row the user posted.

I would advise to avoid the implicit grouping offered by MySQL where possible, by this i mean that your query has allowed you to select ID , Time and seconds , even though they are not contained in an aggregate function or the group by clause.

In this statement:

SELECT  *
FROM    namethatchampion_stats
GROUP BY User
ORDER BY Seconds

You are saying give me one row (at random) for each user, then order these random rows by seconds, so even though you have the order by, this does not affect the grouping:

The MySQL Docs state

The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause.

As such unless your columns excluded from an aggregate and the group by are functionally dependent on a column included in the group by (eg a primary key), then use explicit grouping. In your scenario to get all the rows from your table you could use:

SELECT  stat.ID,
        stat.User,
        stat.Seconds,
        stat.Time
FROM    NamethatChampion_stats Stat
        INNER JOIN
        (   SELECT  User, MIN(Seconds) AS Seconds
            FROM    NamethatChampion_stats
            GROUP BY User
        ) MaxStat
            ON MaxStat.User = stat.User
            AND MaxStat.Seconds = stat.Seconds
ORDER BY Seconds ASC
LIMIT 100

Example on SQL Fiddle

The Drawback of the above method is that if a user has 2 records with the same fastest time both will be returned. It would need further aggregation to remove these duplicates (you'd probably need to limit by the first or last test with the same score).

I assume you want the best scores of every student - and that by "best" you min MIN(seconds) . If that is what you want, here is the way:

SELECT user, MIN(seconds) AS best_score
FROM namethatchampion_stats
GROUP BY user
ORDER BY best_score ASC
    LIMIT 100 ;

Your ORDER BY statement should be using the time column containing the date their tests are submitted, not seconds . (Assuming it contains a full date. If it's only the time then this goes out the window).

This will get you the fastest time for every user:

SELECT user, MIN(seconds) 
FROM namethatchampion_stats
GROUP BY user 
LIMIT 100;

Is this what you wanted?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM