Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MAX and GROUP BY don't return expected values

After searching for a couple of hours on the website, I couldn't find the right answer to my problem, or the answer was too complicated. I have some statistics, from a minecraft server and I want to know which blocks are created the most by whom. So I started with GROUP BY and MAX, but it didn't return the right values. The MAX value is good, but it conflicts with the itemid and the playerid. It just selects the first id and playername. (NOTE: each playerid has a seperate row for each item!!!) The query is as following:

SELECT  `playername` ,  `itemid` , MAX( destroyed ) 
FROM  `blockstats_typed` 
GROUP BY  `itemid` 
LIMIT 0 , 30

The fields that are there are playername, itemid, created and destroyed. I hope you guys can help me...

If you need more info, just say so!

Edit 1 (Table schema):

Column type description
id int(10) id of the row (AI)
playername varchar(50) playername
itemid smallint(5) id of the item
created int(10) times created
destroyed int(10) times destroyed
like image 693
Douwe de Haan Avatar asked Feb 19 '26 19:02

Douwe de Haan


1 Answers

Only MySQL and PostgreSQL (but PostgreSQL does it in a much more limited way; and a comment tells me that SQLite mimics MySQL in this) allow you to omit columns (expressions) from the GROUP BY clause that are in the select-list but are not aggregates. If you want the item ID, the maximum number of times it was destroyed, and the user ID (or IDs) that did that, you have to write a more complex query.

So, you might be after:

SELECT playername,  itemid, MAX(destroyed) 
  FROM blockstats_typed
 GROUP BY playername, itemid 
 LIMIT 0, 30

Or you might be after:

SELECT b.PlayerName, s.ItemID, s.MaxDestroyed
  FROM BlockStats_Typed AS b
  JOIN (SELECT ItemID, MAX(Destroyed) AS MaxDestroyed
          FROM BlockStats_Typed
         GROUP BY ItemID
         LIMIT 0, 30
       ) AS s
    ON b.ItemID = s.ItemID AND b.Destroyed = s.MaxDestroyed;

Note that if some item is destroyed, say, 237,000 times by two players, you will get back both players' names (if that ItemID is in the top 30, of course).

Both are valid queries; they do different things, though. You'll have to decide which, if either, is correct for what you're trying to do. And if neither is correct, you probably need to clarify your question.

(I'm not certain that the LIMIT is allowed where I've written it. If not, place it at the end. And you might want to add an ORDER BY clause with a DESC qualifier to ensure that the limit clause shows the most interesting rows; GROUP BY does not guarantee sorting.)

like image 120
Jonathan Leffler Avatar answered Feb 21 '26 09:02

Jonathan Leffler



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!