0

I have a DB schema something like this:

CREATE TABLE projects (project_id int);
CREATE TABLE project_members (user_id int, project_id int);
CREATE TABLE project_issues (issue_id int, project_id int);

What I want is to find all projects which have 10 or more members as well as 10 or more issues. I am struggling to come up with a query for this.

I want output something similar to:

project_id | members | issues
-----------+---------+-------
65         | 100     | 23
93         | 78      | 45

Preferably sorted by members then issues.

I have come up with:

SELECT projects.project_id, COUNT(project_members.user_id) FROM 
project_members LEFT JOIN projects ON 
project_members.project_id = projects.project_id GROUP BY projects
ORDER BY count;

but do not know how to take it to the next level in counting the issues as well.

I am using PostgreSQL 9.1

4

2 回答 2

4

A bit simpler & faster:

SELECT p.project_id, m.members, i.issues
FROM   projects p
JOIN  (
    SELECT project_id, count(*) AS members 
    FROM   project_members 
    GROUP  BY project_id
    HAVING count(*) >= 10
    ) m USING (project_id)
JOIN  (
    SELECT project_id, COUNT(*) AS issues 
    FROM   project_issues
    GROUP  BY project_id
    HAVING count(*) >= 10
    ) i  USING (project_id)
ORDER  BY m.members DESC, i.issues DESC;

Since you want projects,

which have 10 or more members as well as 10 or more issues

.. you can eliminate non-qualifying candidates early with JOIN and HAVING for a faster result.
Plus some other minor tweaks.

And make that >= 10 or > 9 for "10 or more"!

Be wary of "proxy cross joins":
Two SQL LEFT JOINS produce incorrect result

于 2013-06-17T22:51:44.733 回答
2

This could probably be done more efficient, but it gives the correct results.

SELECT 
  p.project_id,
  m.members,
  i.issues
FROM projects AS p
LEFT JOIN 
  (
      SELECT project_id, COUNT(user_id) AS members 
      FROM project_members 
      GROUP BY project_id
  ) AS m
ON p.project_id = m.project_id
LEFT JOIN 
  (
      SELECT project_id, COUNT(issue_id) AS issues 
      FROM project_issues
      GROUP BY project_id
  ) AS i
ON p.project_id = i.project_id
WHERE members > 10 AND issues > 10
ORDER BY members, issues;
于 2013-06-17T22:38:15.627 回答