Question

For those of you familiar with Minecraft, I am trying to count the number of blocks of each type broken by each user in a single SELECT query. I think that this is called a GROUP BY aggregate function. I think that I need to use multiple aggregate functions to accomplish my end-goal.

So far, I have only been able to:

  • Count the number of blocks of each type that have been broken
  • Count the total number of blocks broken by each user

I think that I need to use a GROUP BY function to COUNT the number of times that each block is broken, then GROUP by each user in a sub-query.


Problem pseudocode:

  • SELECT the player, block_id, count(*) WHERE the action_type is equal to "block-break"
  • COUNT the number times that a block has been broken (by counting the number of occurrences for each block_id)
  • GROUP BY the block_id

What I've tried: (output)

SELECT player, block_id, COUNT(block_id) FROM prism_actions WHERE action_type = 'block-break' GROUP BY block_id;

Also:([output])2

  • This function appears to compute the appropriate value.

SELECT player, block_id, count(*) as count from prism_actions where action_type = 'block-break' group by block_id,player order by block_id;


Table (prism_actions)

Field Type id int(11) unsigned action_time timestamp action_type varchar(20) player varchar(16) world varchar(255) x int(11) y smallint(5) z int(11) block_id mediumint(5) block_subid mediumint(5) old_block_id mediumint(5) old_block_subid mediumint(5) data varchar(255)


I have performed a similar GROUP BY aggregate query to count #(deaths|kills|blocks broken|blocks placed) per player

  • This query works as expected, but only requires a single GROUP BY function
  • Computes the SUM for each action based on the action_type (i.e. player-kill, player-death, block-break, block-place
  • Output is available below:

lower(player) kills deaths blocks_broken blocks_placed joey 41 4 4911 2678 kate 74 1 4944 4762 bill 129 4 2782 1271 jack 335 12 12403 5886

Code: SELECT LOWER(player), SUM(CASE WHEN action_type = 'player-kill' THEN 1 ELSE 0 END) AS kills, SUM(CASE WHEN action_type = 'player-death' THEN 1 ELSE 0 END) AS deaths, SUM(CASE WHEN action_type = 'block-break' THEN 1 ELSE 0 END) AS blocks_broken, SUM(CASE WHEN action_type = 'block-place' THEN 1 ELSE 0 END) AS blocks_placed FROM prism_actions WHERE action_type IN ('block-break', 'block-place', 'player-kill', 'player-death') AND LOWER(player) NOT IN ('creeper', 'fireball', 'environment') GROUP BY player;


Thank you in advance.

I realize that my rep is low on StackOverflow, but I hope that this does not influence your answer, or lead to any form of discrimination.

Was it helpful?

Solution

Use the ROLLUP modifier here to get what you're after.

SELECT player, block_id, count(*) as count 
from prism_actions 
where action_type = 'block-break' 
group by player, block_id WITH ROLLUP
order by block_id;

This will give a record set similar to

Player | Block | Count
NULL     NULL    100
1        NULL    100
1        1       75
1        2       25

Where player =1 and block = NULL is the grand total, below that is the count by block type.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top