0

I am trying to select from a table with the average of columns from other tables from other tables; The schema is as follows.

Students (sid, firstname, lastname, status, gpa, email)

Enrollments (sid, classid, lgrade)

Grades (lgrade, ngrade)

And the erroneous query is,

select sid, lastname, 
avg( select g.ngrade from grades g, enrollments e 
    where e.sid = sid and g.lgrade = e.lgrade and e.lgrade is not null 
    and g.ngrade is not null) as cgpa
from students
order by cgpa asc;
6
  • The error I am getting is EXPRESION MISSING...on line 2 Commented Apr 8, 2013 at 23:44
  • 2
    Wouldn't it be better to put the average inside the subquery? select sid, lastname, (select avg(g.ngrade) from ...) ...) Commented Apr 8, 2013 at 23:48
  • Will that give me average of all of the values in that column or the result would be many tuples with a column? I am unable to imagine here. Commented Apr 8, 2013 at 23:54
  • Yes, that worked , but with the wrong results, which means the problem is with the where clause. I'll check that! Thanks! Commented Apr 8, 2013 at 23:57
  • 1
    Consider putting the subquery in the from clause grouping by sid and joining with students Commented Apr 9, 2013 at 0:00

3 Answers 3

1

Take the semi-colon out of your subquery.

Sign up to request clarification or add additional context in comments.

2 Comments

The error is still there without semicolon, ERROR at line 2: ORA-00936: missing expression
the semi-colon has been removed from the post.
1

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?

2 Comments

Remove the , after grades g in your second query.
What is the purpose of on e.sid = e.sid in your ON expression?
0

Two INNER JOINs without sub-queries - please try.

SELECT s.sid, s.lastname, avg(g.ngrade) cgpa
FROM Students s
JOIN Enrollments e ON s.sid = e.sid
JOIN Grades g ON e.lgrade=g.lgrade
GROUP BY s.sid, s.lastname
ORDER BY 3;

1 Comment

It's s.sid, not s.cid in your GROUP BY statement.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.