我在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
我为一个或多个项目获得了正确的结果,但没有项目的联系人被忽略。也许在这里结合?不确定。
答案 0 :(得分:0)
这应该有效:
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
答案 1 :(得分:0)
列出合约无合约的合约(无合约)
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 for null contract和Inner join来查找所有匹配项,然后根据状态进行过滤。
我列出的两个代码只选择记录/连接,因此您必须以您需要的任何方式使用结果(计数,我假设)。
答案 2 :(得分:0)
我这样解决了:
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
谢谢大家的回答和支持。