Forum Moderators: open
[edited by: Tusserte at 12:56 pm (utc) on Sep. 3, 2008]
1) values that appear in the GROUP BY and
2) Aggregate functions like AVG(), SUM(), COUNT(), etc.
You were only using 'item' in the GROUP BY but you were returning all fields in the table (*) in the SELECT. Thus the error.
SELECT item, AVG(score)
FROM reviews
GROUP BY item
ORDER BY AVG(score) DESC
should get you a list of items ordered by their average score descending assuming 'item' uniquely identifies a particular thing being scored.
I'm guessing you have a separate 'item' table where the column 'item' is the primary key and that reviews.item is just a foreign key reference back to item.item. If that is the case and the item table had an item_name that you wanted to display you could do something like:
SELECT r.Item, i.ItemName, AVG(r.Score)
FROM review AS r
JOIN item AS i ON r.item = i.item
GROUP BY r.Item, i.ItemName
ORDER BY AVG(r.Score) DESC
NOTE: Because I wanted to return ItemName, it had to also appear in the GROUP BY.
As far as getting the ranking, I'm guessing you want to know which item has, say, the 3rd highest score or the 19th highest score.
The only way I could think to do that would be using another table. Not sure how often you would re-calculate the averages. If it's every time a user wants to query it then this approach is probably not good. But if you do it once per day or once per week, you could store the rankings and average scores in a table and have your web simply pull back the values from the table. In that case you could create a table something like:
CREATE TABLE tItemAverageScore (
Rank INT NOT NULL AUTO_INCREMENT,
Item INT,
AverageScore DECIMAL(2)
)
Schedule a stored procedure to run once per day or week that does something like:
DROP TABLE tItemAverageScore
CREATE TABLE tItemAverageScore (
Rank INT NOT NULL AUTO_INCREMENT,
Item INT,
AverageScore DECIMAL(2)
)
INSERT INTO tItemAverageScore (Item, AverageScore)
SELECT item, AVG(score)
FROM review
GROUP BY item
ORDER BY AVG(score) DESC
This would drop and recreate the table when the proc ran and then repopulate it based on results in your review table. It assumes you want the highest AVG(score) to rank as #1, 2nd highest AVG(score) to rank as #2, etc. I'm guessing auto increments always start at 1 in MySQL (sorry I'm MS SQL*Server / Oracle experienced).
Then your web app could do something similar to the following if you wanted to show the top 10 items in order of ranking:
SELECT i.*, ias.Rank, ias.AverageScore
FROM Item AS i
JOIN tItemAverageScore AS ias ON i.item = ias.Item
WHERE ias.Rank <= 11
ORDER BY ias.Rank
Hope that helps or at least gets your wheels turning...
DISCLAIMER: I haven't checked any of the above syntax. Just keyed it in on the fly. I don't have a copy of MySQL to play with. Sorry.
[edited by: ZydoSEO at 7:42 pm (utc) on Sep. 3, 2008]