有两个表:
伙伴
id | name
--------------
1 | partner_1
2 | partner_2
3 | partner_3
4 | partner_4
合同
id | name | is_active
---------------------------
1 | contract_1 | 1
2 | contract_2 | 0
3 | contract_3 | 1
4 | contract_4 | 0
5 | contract_5 | 0
第三个表格将前两个表格与多对多关系相关联
partner_contract
partner_id | contract_id
------------------------
1 | 1
1 | 2
2 | 3
2 | 2
2 | 4
3 | 5
每个合作伙伴可以有多个合同,其中 ONLY ONE 可以是活动的,有些是非活动的。 合伙人也可能根本没有合同。
我需要一个查询,显示所有合作伙伴以及有效合同。如果合作伙伴没有'有一个有效合同,显示NULL。
partner_id | partner_name | contract_name
-----------------------------------------
1 | partner_1 | contract_1
2 | partner_2 | contract_3
3 | partner_3 | NULL
4 | partner_4 | NULL
我找到了一个解决方案,但在我看来它并不完美。
SELECT
p.id AS partner_id,
p.name AS partner_name,
active_contract.name AS contract_name
FROM partner p
LEFT JOIN (
SELECT *
FROM contract c
LEFT JOIN partner_contract pc on pc.contract_id = c.id
WHERE c.is_active = 1
) active_contract
ON active_contract.partner_id = p.id
有更优雅的解决方案吗?
答案 0 :(得分:0)
Ray(已删除)查询接近正确的解决方案。合同上的条件应该是on
子句,而不是where
子句:
SELECT p.id AS partner_id, p.name AS partner_name, c.name AS contract_name
FROM partner p LEFT JOIN
partner_contract pc
ON p.id = pc.partner_id LEFT JOIN
contract c
ON pc.contract_id = c.id AND c.is_active = 1;
编辑:
好的,上面的错误。可以使用group by
:
SELECT p.id AS partner_id, p.name AS partner_name, MAX(c.name) AS contract_name
FROM partner p LEFT JOIN
partner_contract pc
ON p.id = pc.partner_id LEFT JOIN
contract c
ON pc.contract_id = c.id AND c.is_active = 1
GROUP BY p.id, p.name;
更优雅的解决方案(在我看来):
SELECT p.*,
(select name
from partner_contract pc join
contract c
on pc.contract_id = c.id AND c.is_active = 1
where p.id = pc.partner_id
) as contract_name
FROM partner p;
这可以利用索引,不需要聚合。