Please try the following...
set @rowNum := 0;
set @state := '';
SELECT state,
AVG( perDem ) AS avgPerDem,
AVG( perGOP ) AS avgPerGOP,
AVG( perInd ) AS avgPerInd
FROM
(
SELECT day AS day,
state AS state,
perDem AS perDem,
perGOP AS perGOP,
perInd AS perInd,
@rowNum := if ( @state = state,
@rowNum + 1,
1 ) AS rowNum,
@state := state AS valueHolder
FROM polls
ORDER BY state,
day DESC
) rowNumGenerator
WHERE rowNum <= 3
GROUP BY state
ORDER BY state;
Here the inner query returns sorts the contents sorts the contents of polls
by state
in alphabetical order and for each state it further sorts the rows by day
, from largest to smallest.
Once this is done it returns the fields of interest (day
, state
, perDem
, perGOP
and perInd
) as well as a row number that it generates based on the following pattern...
Where a new state is encountered it gives this first row a row number of 1
.
Each subsequent row for that state is given the next available row number.
This effectively assigns a number to each record's position within the ordered list, relative to the first record for that state
.
The outer query selects only those rows whose position / row number places it in the top three for its state
.
The records of the resulting dataset are then grouped by state
. Please note that the outer SELECT
statement does not know the grouping used by the inner one, and can not safely assume it. Thus it will assume that there is no grouping unless otherwise instructed.
The mean average for each state's per
fields are then calculated and all specified fields are returned to the user.
If you have any questions or comments, then please feel free to post a Comment accordingly.