加入计数
counting in joins
我在 contact
和 project
之间有很多关联。
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
感谢大家的回答和支持。
我在 contact
和 project
之间有很多关联。
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
感谢大家的回答和支持。