【问题标题】:counting in joins计算联接
【发布时间】:2016-03-17 13:16:09
【问题描述】:

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 个或多个项目的正确结果,但没有项目的联系人被忽略。也许这里有工会?不确定。

【问题讨论】:

  • statsus 在项目中应该是status
  • 是的,我已经更正了错字,谢谢!
  • 没问题。希望我能帮助的不仅仅是一个错字。

标签: sql database postgresql join left-join


【解决方案1】:

列出合约上为 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

我无法测试代码,但您需要的是用于空合约的左连接和内连接以查找所有匹配项,然后根据状态进行过滤。

我列出的两个代码都只选择记录/连接,所以你必须以任何你需要的方式使用结果(计数,我假设)。

【讨论】:

    【解决方案2】:

    这应该有效:

    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
    

    【讨论】:

      【解决方案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'
                          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
      

      感谢大家的回答和支持。

      【讨论】:

        猜你喜欢
        • 2010-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-20
        • 2013-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多