tastyfish
tastyfish

Reputation: 23

MySql: Finding the MAX value of the SUM grouped by column

I have a table that includes names, items, types, and a count per item. I need to find a way to determine the name that has the MAX count in each type.

Example table:

---------------------------------------
| name | item     | type      | count |
| ------------------------------------|
| Dave | carrot   | vegetable | 2     |
| Dave | broccoli | vegetable | 3     |
| Tom  | spinach  | vegetable | 2     |
| Jon  | swiss    | cheese    | 3     |
| Mark | cheddar  | cheese    | 5     |
| Jon  | cheddar  | cheese    | 6     |
| Tony | onion    | vegetable | 3     |

I want to find the names of each person with the highest SUM(count) in each type. This is my expected result:

----------------------------
| name | type      | count |
| -------------------------|
| Dave | vegetable | 5     |
| Jon  | cheese    | 9     |

I'm trying to see if there is an elegant way of doing it other than queries for every name and then manually calculating the MAX.

Upvotes: 2

Views: 2498

Answers (3)

Anthony
Anthony

Reputation: 37045

This may not be optimal, but it's pretty straightforward:

SELECT name, type, MAX(count) as count FROM (
   SELECT name, type, SUM(count) as count
    FROM mytable
    GROUP BY type, name
) as rank
GROUP BY type;

The inner query returns each name and the sum of the type for that name, like:

NAME    TYPE    COUNT
Jon     cheese      9
Dave    vegetable   5
Mark    cheese      5
Tony    vegetable   3
Tom     vegetable   2

Then the outer query groups by type, thus only returning one name per type, and the having max() returns the top name for the type.

This will not return tied names, but will return the same name for different types, so if suddenly gave Dave 10 in swiss, he'd show up as the top for vegetable and cheese.

Upvotes: 3

Mark Byers
Mark Byers

Reputation: 838076

First calculate the totals for each name/category combination. Do this either in a subquery or a view. I'm going to choose a view to reduce code bloat, since it will be needed more than once.

CREATE VIEW totals AS
SELECT name, type, SUM(count) AS count
FROM yourtable
GROUP BY name, type
----------------------------
| name | type      | count |
| -------------------------|
| Dave | vegetable | 5     |
| Tony | vegetable | 3     |
| Tom  | vegetable | 2     |
| Jon  | cheese    | 9     |
| Mark | cheese    | 5     |
----------------------------

Now you need to find the maximum count for each type.

SELECT type, MAX(count) AS max_count
FROM totals
GROUP BY type
-------------------------
| type      | max_count |
| -----------------------
| vegetable | 5         |
| cheese    | 9         |
-------------------------

Now you just need to query the view totals for all rows where (type, count) is equal to any of the pairs in the second result set. I've already done most of the work for you. I'll leave you to finish it off.

Upvotes: 2

Jeff Allen
Jeff Allen

Reputation: 17517

Without having the database in front of me, give this a shot:

SELECT * FROM Table T 
  LEFT JOIN (SELECT type, MAX(count) AS max FROM Table GROUP BY type) AS maxType 
  ON T.type = maxType.type 
    AND t.count = max.count

Upvotes: 0

Related Questions