2

I'd like to reference aggregate function like this:

Sample Data:

+-----------+----------+-------+
| member_id | group_id | score |
+-----------+----------+-------+
| 1 | 1 | 12 |
| 2 | 1 | 2 |
| 3 | 1 | 20 |
| 4 | 2 | 40 |
| 5 | 2 | 4 |
| 6 | 3 | 19 |
| 7 | 3 | 17 |
+-----------+----------+-------+

Query:

SELECT MAX(IF(score = MAX(score), member_id, NULL)) AS member
FROM members
GROUP BY group_id

Expected Result:

+-----------+
| member_id |
+-----------+
| 3 |
| 4 |
| 6 |
+-----------+

Fiddle: http://sqlfiddle.com/#!9/08af68/2

But this results in the error:

Invalid use of group function

I've simplified things here but I'm trying to use this in a much more complex scenario where the score value is the result of a large complex query. Doing this the standard way which I'm aware of results in something that looks a bit ridiculous since the initial query to get the working values is upwards of 35 lines of code.

QUESTION: Why are aggregate functions not allowed to be used like this? Is there a workaround that doesn't involve effectively duplicating the entire SELECT simply to get the MAX() value for use as a point of reference?

asked Jul 18, 2018 at 19:39
0

2 Answers 2

1

Cleaver. But no go.

To achieve what you ask for would take two passes over the data. Things don't work that way.

The first pass is to find the max for each group; the second pass is to check all the value against the maxes.

You can do it with a subquery, an @variable or several other ways. Follow the tag to see ways to do "groupwise max".

answered Jul 19, 2018 at 1:58
3
  • thank you, you've answered the "is there a workaround" part of my question, but I'd really like to know why we are not allowed to do this in one pass? MAX(score) can clearly be retrieved but not compared against and this limitation is a bit mysterious to me. Commented Jul 19, 2018 at 2:50
  • 1
    @billynoah - Another possible answer is that SQL is nearly half a century old; it was really advanced for the time; you are asking for something even more advanced. Commented Jul 19, 2018 at 4:06
  • I appreciate your input Rick and and putting things in historical context is helpful, but I'm looking for more of an explanation about the limitation here. It doesn't have to be amazingly in depth, but should be a bit more than "Things don't work that way". Commented Jul 19, 2018 at 5:08
1

It seems that max can't use twice for same attribute.

So, you are expecting member_id of row selected.

As below

+-----------+----------+-------+
| member_id | group_id | score |
+-----------+----------+-------+
| 3 | 1 | 20 |
| 4 | 2 | 40 |
| 6 | 3 | 19 |
+-----------+----------+-------+

But result is different.

+-----------+----------+-------+
| member_id | group_id | score |
+-----------+----------+-------+
| 1 | 1 | 20 |
| 4 | 2 | 40 |
| 6 | 3 | 19 |
+-----------+----------+-------+

Because score max value is 20 for group_id 1. However member_id is selected first row value.

Change like this

SELECT 
 ( SELECT member_id 
 FROM members m 
 WHERE m.score = MAX(members.score) 
 ) AS member
FROM members
GROUP BY group_id
answered Jul 19, 2018 at 2:07
1
  • this is a cool trick but doesn't answer my question. the problem as I've tried to convey is that score isn't really a value in the table - it's the result of a big complex query. So doing it your way (or the way I'm doing it in real life) is not so simple as querying the table members - it would require reproducing the entire subquery, which is essentially what RickJames has told me above, is unavoidable. thanks anyway for your effort Commented Jul 19, 2018 at 2:47

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.