skip to Main Content

I’m trying to select the row that contains the largest number and have accomplished it using this fairly simple query:

SELECT s1.score, name
FROM scores s1
JOIN (
    SELECT id, MAX(score) score
    FROM scores
    GROUP BY id
) s2 ON s1.score = s2.score 

All it does (If im not wrong), is just checking if the score field is equal the the MAX(score). So why can’t we just do it using one single SELECT statement ?. Something like this:

SELECT id, score
FROM scores
GROUP BY id
HAVING MAX(score) = score

*The code above does not work, I want to ask why it is not working, because its essentially doing the same thing as the previous code I posted

Also here’s the data I’m working with:

Data

3

Answers


  1. It returns all persons with same score which the score is the max:

    WITH CTE AS (
    SELECT *, ROW_NUMBER() OVER(ORDER BY score desc) RN
    FROM scores
    )
    SELECT * FROM CTE
    WHERE CTE.RN = 1
    
    Login or Signup to reply.
  2. Here’s what your queries return

    DROP table if exists t;
    
    create table t
    (id int,score int);
    
    insert into t values
    (1,10),(2,20),(3,20);
    
    SELECT s1.id,s1.score
    FROM t s1
    JOIN (
        SELECT id, MAX(score) score
        FROM t
        GROUP BY id
    ) s2 ON s1.score = s2.score ;
    
    +------+-------+
    | id   | score |
    +------+-------+
    |    1 |    10 |
    |    2 |    20 |
    |    2 |    20 |
    |    3 |    20 |
    |    3 |    20 |
    +------+-------+
    5 rows in set (0.001 sec)
    
    SELECT id, score,max(score)
    FROM t
    GROUP BY id
    HAVING MAX(score) = score
    
    +------+-------+------------+
    | id   | score | max(score) |
    +------+-------+------------+
    |    1 |    10 |         10 |
    |    2 |    20 |         20 |
    |    3 |    20 |         20 |
    +------+-------+------------+
    3 rows in set (0.001 sec)
    

    Neither result seems to be what you are looking for. You could clarify by posting sample data and desired outcome.

    Login or Signup to reply.
  3. The problem in your second query is the fact that the GROUP BY clause requires all non-aggregated fields within its context. In your case you are dealing with three fields (namely "id", "score" and "MAX(score)") and you’re referencing only one (namely "id") inside the GROUP BY clause.

    Fixing that would require you to add the non-aggregated "score" field inside your GROUP BY clause, as follows:

    SELECT id, score
    FROM scores
    GROUP BY id, score
    HAVING MAX(score) = score
    

    Though this would lead to a wrong aggregation and output, because it would attempt to get the maximum score for each combination of (id, score).

    And if you’d attempt to remove the "score" field from both the SELECT and GROUP BY clauses, to solve the non-aggregated columns issue, as follows:

    SELECT id
    FROM scores
    GROUP BY id
    HAVING MAX(score) = score
    

    Then the HAVING clause would complain as long it references the "score" field but it is found neither within the SELECT clause nor within the GROUP BY clause.

    There’s really no way for you to use that kind of notation, as it either violates the full GROUP_BY mode, or it just returns the wrong output.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search