0

I have the following query that gets the papers grade listing.

SELECT DISTINCT papers.paper_id, papers.paper_title, AVG(paper_judge_participations.paper_judge_participation_score) AS final_grade,
(SELECT array_agg(paper_author_name) FROM paper_authors as authors WHERE authors.paper_id=papers.paper_id )::varchar as paper_author_name
FROM papers 
FULL JOIN paper_categories ON paper_categories.paper_category_id=papers.paper_category_id
LEFT JOIN paper_judge_participations ON papers.paper_id = paper_judge_participations.paper_id 
WHERE ((papers.paper_note IS NULL AND final_grade >= 7) OR (papers.paper_note IS NOT NULL AND papers.paper_note >= 7)) AND papers.paper_category_id = 1
GROUP BY papers.paper_id ORDER BY final_grade, papers.paper_note;

I want to see if the final_grade variable from the the averae result is more than 7 but I get the error:

ERROR:  column "final_grade" does not exist
LINE 6: WHERE ((papers.paper_note IS NULL AND final_grade >= 7) OR (...

How can I use the average result on my WHERE condition?

3
  • AVG() is not allowed on the where clauses. ): @vkp Commented Aug 26, 2015 at 18:38
  • You need to put the avg condition in a "HAVING" clause, which comes after the GROUP BY Commented Aug 26, 2015 at 18:38
  • I'm new to SQL. Can you please answer the question with the script, @mlinth ? Commented Aug 26, 2015 at 18:40

1 Answer 1

2

The distinct is unnecessary in the SELECT. Also you need to move the logic to the HAVING clause:

SELECT p.paper_id, p.paper_title,
       AVG(pjp.paper_judge_participation_score) AS final_grade,
       (SELECT string_agg(paper_author_name)
        FROM paper_authors pa
        WHERE pa.paper_id = p.paper_id
       ) as paper_author_name
FROM papers p LEFT JOIN
     paper_categories pc
     ON pc.paper_category_id = p.paper_category_id LEFT JOIN 
     paper_judge_participations pjp
     ON p.paper_id = pjp.paper_id 
HAVING p.paper_category_id = 1
GROUP BY p.paper_id
HAVING (p.paper_note IS NULL AND final_grade >= 7) OR
       (p.paper_note IS NOT NULL AND p.paper_note >= 7) AND 
ORDER BY final_grade, p.paper_note;

Comments:

  • The FULL OUTER JOIN is being turned into a LEFT OUTER JOIN by the WHERE clause. So, you might as well be explicit.
  • Instead of doing array_agg() and converting the results to a string, how about just using string_agg()?
  • Table aliases make the query easier to write and read.
  • And of course, the conditions on the final grade have been moved to the HAVING clause. The condition on the group stays in the WHERE.

Personally, I find it strange that you are using a correlated subquery for one aggregation and explicit aggregation for the other. I suppose that is a matter of preference. Under the circumstance, you might consider using a correlated subquery for both.

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

2 Comments

The system I'm working uses a old version of postgresql and some functions like string_agg() don't exist.
I ended using the having, and it's working now. Thanks.

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.