Joining a derived table postgres

1.2k views Asked by At

I have 4 tables:

  • Competencies: a list of obviously competencies, static and a library
  • Competency Levels: refers to an associated group of competencies and has a number of competencies I am testing for
  • call_competency: a list of all 'calls' that have recorded the specified competency
  • competency_review_status: proving whether each call_competency was reviewed

Now I am trying to write this query to count a total and spit out the competency, id and whether a user has reached the limit. Everything works except for when I add the user. I am not sure what I am doing wrong, once I limit call competency by user in the where clause, I get a small subset that ONLY exists in call_competency returned when I want the entire list of competencies.

The competencies not reached should be false, ones recorded appropriate number true. A FULL list from the competency table.

I added the derived table, not sure if this is right, obviously it doesn't run properly, not sure what I'm doing wrong and I'm wasting time. Any help much appreciated.

SELECT comp.id, comp.shortname, comp.description,
       CASE WHEN sum(CASE WHEN crs.grade = 'Pass' THEN 1 ELSE CASE WHEN crs.grade = 'Fail' THEN -1 ELSE 0 END END) >= comp_l.competency_break_level
       THEN TRUE ELSE FALSE END
FROM competencies comp
INNER JOIN competency_levels comp_l  ON comp_l.competency_group = comp.competency_group
LEFT OUTER JOIN (
  SELECT competency_id 
  FROM call_competency
  WHERE call_competency.user_id IN (
    SELECT users.id FROM users WHERE email= _studentemail
  )
) call_c ON call_c.competency_id = comp.id
LEFT OUTER JOIN competency_review_status crs ON crs.id = call_competency.review_status_id
GROUP BY comp.id, comp.shortname, comp.description, comp_l.competency_break_level
ORDER BY comp.id;
1

There are 1 answers

1
Patrick On BEST ANSWER

(Shooting from the hip, no installation to test)

It looks like the below should do the trick. You apparently had some of the joins mixed up, with a column from a relation that was not referenced. Also, the CASE statement in the main query could be much cleaner.

SELECT comp.id, comp.shortname, comp.description,
       (sum(CASE WHEN crs.grade = 'Pass' THEN 1 WHEN crs.grade = 'Fail' THEN -1 ELSE 0 END) >= comp_l.competency_break_level) AS reached_limit
FROM competencies comp
JOIN competency_levels comp_l USING (competency_group)
LEFT JOIN (
  SELECT competency_id, review_status_id
  FROM call_competency
  JOIN users ON id = user_id
  WHERE email = _studentemail
) call_c ON call_c.competency_id = comp.id
LEFT JOIN competency_review_status crs ON crs.id = call_c.review_status_id
GROUP BY comp.id, comp.shortname, comp.description
ORDER BY comp.id;