There are several issues:
- Remove the semicolon from the subquery.
- You're attempting to use a correlated subquery as a value expression. That's fine, but you have to wrap it in parentheses to do so. I only see one set of parentheses, the ones for the
avg() function.
- You're also missing an alias on a column. For clarity in expressing your intent, you should be consistent and use aliases throughout.
- Last, a
GROUP BY clause is required somewhere.
All in all, I think the aggregate should be inside the parentheses.
Try:
select
sid,
lastname,
(
select avg(g.ngrade)
from grades g, enrollments e
where e.sid = sid and g.lgrade = e.lgrade
and g.ngrade is not null
) as cgpa
from students
order by cgpa asc;
Other notes: e.lgrade is not null is not needed since the condition g.lgrade = e.lgrade already ensures it won't be null.
Last, I encourage you to learn ANSI join syntax. You'll thank me later. Seriously, using old-style joins is awful.
select
s.sid,
s.lastname,
(
select avg(g.ngrade)
from
grades g
inner join enrollments e
on g.lgrade = e.lgrade
where
g.ngrade is not null
and s.sid = g.sid
) as cgpa
from students s
order by cgpa asc;
In fact, I have a suspicion that simply rewriting the query this way will help expose what's wrong with it--it looks to me like maybe the grades and enrollments tables need another join condition?
select sid, lastname, (select avg(g.ngrade) from ...) ...)fromclause grouping bysidand joining withstudents