加入计数

counting in joins

我在 contactproject 之间有很多关联。

contact:
+-----------------+--------------+------+-----+---------+----------------+
| Field           | Type         | Null | Key | Default | Extra          |
+-----------------+--------------+------+-----+---------+----------------+
| id              | int(11)      | NO   | PRI | NULL    | auto_increment |
| deleted         | boolean      | NO   |     | NULL    |                |
+-----------------+--------------+------+-----+---------+----------------+

project:
+-----------------+--------------+------+-----+---------+----------------+
| Field           | Type         | Null | Key | Default | Extra          |
+-----------------+--------------+------+-----+---------+----------------+
| id              | int(11)      | NO   | PRI | NULL    | auto_increment |
| status          | varchar      | NO   |     | NULL    |                |
+-----------------+--------------+------+-----+---------+----------------+

project_contact:
+---------------+---------+------+-----+---------+-------+
| Field         | Type    | Null | Key | Default | Extra |
+---------------+---------+------+-----+---------+-------+
| project_id    | int(11) | NO   | PRI | NULL    |       |
| contact_id    | int(11) | NO   | PRI | NULL    |       |
| proj_con_role | varchar | NO   |     | NULL    |       |
+---------------+---------+------+-----+---------+-------+

我想统计有多少联系人与没有项目、一个项目或多个项目相关联。但是,对于后两个(一个项目和多个项目),项目状态必须是 'STATUS_X'. proj_con_role 必须是 'CLIENT' 而且,联系人不得标记为删除。如果我能在一个查询中得到它,那绝对很棒,如果不能,3 个不同的查询也能做到。

到目前为止我有这个:

SELECT   numprojects,
         Count(*) AS numcontacts
FROM     (
                   SELECT    c.id,
                             Count(pc.contact_id) AS numprojects
                   FROM      contact c
                   LEFT JOIN project_contact pc
                   ON        pc.contact_id = c.id
                   AND       pc.proj_con_role = 'CLIENT'
                   WHERE     (
                                       c.deleted isnull
                             OR        c.deleted = false)
                   GROUP BY  c.id ) c
GROUP BY numprojects
ORDER BY numprojects

现在,这工作正常,但对于我的生活,我似乎无法添加项目必须具有特定状态的条件...我不知道如何添加它。任何帮助都会非常棒。

我试过添加:

left join project p on p.status = 'STATUS_X' and p.id = pc.project_id

当然,不是这样的...

稍后编辑 1:

如果我添加:

inner join project p on p.status = 'STATUS_X' and p.id = pc.project_id

我得到了 1 个或多个项目的正确结果,但没有项目的联系人被忽略。也许这里有一个工会?不确定。

这应该有效:

select
case when project_contracts = 0 then '0 projects'
when project_contracts = 1 then '1 project'
else '2+ projects' end as num_of_projects
count(contracts) as contracts
from
    (select 
    c.id as contracts
    sum(case when p.id is null then 0 else 1 end) as projects_contracts
    from contracts c
    left join project_contracts p on p.id = c.id
    group by c.id)
group by case when project_contracts = 0 then '0 projects'
when project_contracts = 1 then '1 project'
else '2+ projects' end

列出合同为 Null 的合同(没有合同)

                   SELECT    *
                   FROM      contact c
                   LEFT JOIN project_contact pc  --Left join = all contacts, even if no join to a contract is made
                   ON        pc.contact_id = c.id
                   AND       pc.proj_con_role = 'CLIENT'
                   WHERE     (c.deleted isnull
                             OR c.deleted = false) 
                             AND pc.id isnull  --Clients with no contacts

对于有合同的联系人

                   SELECT    *
                   FROM      contact c
                   INNER JOIN project_contact pc  --Inner join only shows succesful joins (meaning neither ID can be null)
                   ON        pc.contact_id = c.id
                   AND       pc.proj_con_role = 'CLIENT'
                   WHERE     (c.deleted isnull
                             OR c.deleted = false) 
                             AND pc.status = 'Status_X' --your status

我无法测试代码,但您需要的是针对空合同的 Left Join 和用于查找所有匹配项的 Inner Join,然后根据状态进行过滤。

我只列出了 select 和 records/joins 两个代码,因此您必须以任何需要的方式使用结果(我假设是计数)。

我是这样修复的:

SELECT   numprojects,
         Count(*) AS numcontacts
FROM     (
                    SELECT     c.id,
                               Count(pc.contact_id) AS numprojects
                    FROM       contact c
                    LEFT JOIN  project_contact pc
                    ON         pc.contact_id = c.id
                    AND        pc.proj_con_role = 'CLIENT'
                    INNER JOIN project p
                    ON         p.status = 'STATUS_X'
                    AND        p.id = pc.mandate_id
                    WHERE      (
                                          c.deleted isnull
                               OR         c.deleted = false)
                    GROUP BY   c.id ) c
GROUP BY numprojects
UNION ALL
SELECT   numprojects,
         count(*) AS numcontacts
FROM     (
                   SELECT    c.id,
                             count(pc.contact_id) AS numprojects
                   FROM      contact c
                   LEFT JOIN project_contact pc
                   ON        pc.contact_id = c.id
                   AND       pc.project_contact_role = 'CLIENT'
                   WHERE     (
                                       c.deleted isnull
                             OR        c.deleted = false)
                   GROUP BY  c.id ) c
WHERE    numprojects = 0
GROUP BY numprojects
ORDER BY numprojects

感谢大家的回答和支持。