Reputation: 2851
I'm storing ratings for an item in a table called ratings
.
value
is an integer between 0 and 7 (the rating value).
As an example, let's say showcase_id = 1
has 10 total ratings:
Is there any efficient way I can select the total number of ratings for each specific value, the total number of ratings and the average rating from 1 single query?
e.g. the number of rows/count WHERE value = 6
is 2. Would I need to do 7 separate subqueries?
SELECT AVG(value),COUNT(*),????
FROM ratings
WHERE showcase_id = :showcase_id
Upvotes: 0
Views: 3943
Reputation: 1927
What's wrong with group by?
SELECT AVG(value),COUNT(*), value
FROM ratings
WHERE showcase_id = :showcase_id
GROUP BY value;
EDIT (with the overall avg & totes):
select count(*) total_by_value, value, s1.full_avg, s1.full_total
from ratings r,
(select avg(value) full_avg, count(*) full_total from ratings) s1
group by s1.full_avg, s1.full_total, value;
Upvotes: 0
Reputation: 781848
You can use the WITH ROLLUP
modifier to GROUP BY
to get the counts and average for each value, as well as the totals for everything (if you group by multiple columns it will also create subtotals for each inner group).
SELECT value, AVG(value) AS avg, COUNT(*) as count
FROM ratings
WHERE showcase_id = 1
GROUP BY value WITH ROLLUP
This will produce a row for each value with its count, and then a row with value = NULL
for that aggregates the entire result.
Upvotes: 0
Reputation: 1270523
Are you referring to count(distinct)
?
SELECT AVG(value), COUNT(*), COUNT(DISTINCT value)
FROM ratings
WHERE showcase_id = :showcase_id;
EDIT:
If you want the total for each value, you can stuff this into one column, using a subquery:
SELECT SUM(cnt * value) / SUM(cnt) as average,
SUM(cnt) as total_cnt,
GROUP_CONCAT(value, '-', cnt ORDER BY VALUE) as values
FROM (SELECT value, COUNT(*) as cnt
FROM ratings r
WHERE showcase_id = :showcase_id
GROUP BY value
) r;
Perhaps the subquery meets your needs as well.
Upvotes: 0