What is the difference between WHERE and HAVING? In what order does PostgreSQL logically evaluate the clauses of a SELECT?
Show the explanation
WHERE filters rows before grouping; HAVING filters groups after aggregation. So WHERE cannot use aggregates like count(*), while HAVING usually does.
Logical evaluation order:
FROMandJOINsWHEREGROUP BYHAVINGSELECT(expressions, window functions)DISTINCTORDER BYLIMIT/OFFSET
-- Branches with at least 10 final-year students whose average CGPA is above 7.5
select branch, count(*) as students, round(avg(cgpa), 2) as avg_cgpa
from students
where year = 4 -- row filter: runs first
group by branch
having count(*) >= 10 and avg(cgpa) > 7.5 -- group filter
order by avg_cgpa desc; -- ORDER BY may use the aliasPut row conditions in WHERE whenever possible: it reduces the rows before the more expensive grouping. The evaluation order also explains why a column alias defined in SELECT cannot be used in WHERE.
Original UniCircle question. Last reviewed 22 Oct 2026.
