The error message tells you:
aggregates not allowed in WHERE clause
count()
is an aggregate function. Use the HAVING clause for that.
The query could look like this:
SELECT r.*
FROM recommendations r
JOIN approvals a ON a.recommendation_id = r.id
WHERE r.user_id = $current_user_id
GROUP BY r.id
HAVING count(a.recommendation_id) = 1
With PostgreSQL 9.1 or later it is enough to GROUP BY
the primary key of a table (presuming recommendations.id
is the PK). In Postgres versions before 9.1 you had to include all columns of the SELECT
list that are not aggregated in the GROUP BY
list. With recommendations.*
in the SELECT
list, that would be every single column of the table.
I quote the release notes of PostgreSQL 9.1:
Allow non-GROUP BY
columns in the query target list when the primary
key is specified in the GROUP BY
clause (Peter Eisentraut)
Simpler with a sub-select
Either way, this is simpler and faster, doing the same:
SELECT *
FROM recommendations r
WHERE user_id = $current_user_id
AND (SELECT count(*)
FROM approvals
WHERE recommendation_id = r.id) = 1;
Avoid multiplying rows with a JOIN
a priori, then you don't have to aggregate them back.