4

I have 2 tables.

table 1 (projects): id, name, type

table 2 (project_ratings): project_id, rating

Some projects don't have ratings.

SELECT `p`.`id`, `p`.`name`, AVG(pr.rating) FROM (`projects` p) JOIN `project_ratings` pr ON `p`.`id` = `pr`.`project_id` WHERE `p`.`type` = 'group' OR `p`.`type` = 'user';

I want to return all projects, and return NULL if there aren't any ratings. This query returns only the ones with ratings.

I tried left join, right join, full join, still same thing.

Using CodeIgniter Active Records:

$this->db->select("p.id, p.name, AVG(pr.rating)");
        $this->db->from('projects p');
        $this->db->join('project_ratings pr', 'p.id = pr.project_id');

        $this->db->where('p.type', 'group');
        $this->db->or_where('p.type', 'user');
$res = $this->db->get();

what am I missing?

6
  • 1
    This is the definition of a LEFT JOIN though I think your use of the AVG aggregate isn't going to work for this Commented May 3, 2011 at 2:11
  • I've tried left join... still returns 1 result.. i want all Commented May 3, 2011 at 2:12
  • 1
    I have a feeling you will need a GROUP BY p.id, p.name however I still don't think the third column is going to show the correct values. I may be wrong but too lazy to test this myself Commented May 3, 2011 at 2:14
  • GROUP BY did the trick.. if you could answer it as a whole answer, i can give you credit :) Thank you Commented May 3, 2011 at 2:18
  • along with left outer join. forgot to add that Commented May 3, 2011 at 2:20

5 Answers 5

3

When using an aggregate function (AVG() in this case), you need to specify a GROUP BY clause with the non-aggregate fields, eg

GROUP BY p.id, p.name

To ensure all project references are present regardless of joined ratings, use a LEFT JOIN.

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

Comments

3

The sql that you want would be

         SELECT *
           FROM projects
LEFT OUTER JOIN project_ratings ON projects.id = project_ratings.project_id

I'm not certain how to do that with code igniter.

Comments

2

Try this:

$this->db->select("p.id, p.name, AVG(pr.rating) as average_rating");
$this->db->from('projects p');
$this->db->join('project_ratings pr', 'p.id = pr.project_id', 'left');
$this->db->where('p.type', 'group');
$this->db->group_by('p.id');
$this->db->or_where('p.type', 'user');
$res = $this->db->get();

If there is no rating, average_rating will be NULL.

Comments

0

Query should be:

SELECT `p`.`id`, `p`.`name`, AVG(pr.rating) 
FROM (`projects` p) 
    LEFT OUTER JOIN `project_ratings` pr ON `p`.`id` = `pr`.`project_id` 
WHERE `p`.`type` = 'group' OR `p`.`type` = 'user';

(I don't know how to do that in CodeIgniter :)

Comments

0

You can get an outer join by do this:

    $this->db->join('project_ratings pr', 'p.id = pr.project_id', 'outer');

Comments

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.