MySQL多表关联查询:筛选所有关联记录含指定字符串的公司
嘿,我来帮你搞定这个查询需求!首先咱们先理清楚你的表关联逻辑:n_companies 和 n_contacts 通过 company_id 关联,n_contacts 又和 n_custom 通过 custom_type='contacts' + custom_type_id = n_contacts.id 关联。你要找的是所有关联记录(该公司下所有联系人对应的自定义记录)都包含指定字符串的公司,对吧?
先回顾下你的表结构
n_companies 表:
| id | company_name |
|---|---|
| 1 | Company A |
| 2 | Company B |
n_contacts 表:
| id | company_id | contact_name |
|---|---|---|
| 1 | 1 | John |
| 2 | 1 | Frank |
| 3 | 2 | Bobby |
| 4 | 2 | Sophie |
n_custom 表:
| id | custom_type | custom_type_id | gender | fav_colour |
|---|---|---|---|---|
| 1 | contacts | 1 | male | red |
| 2 | contacts | 2 | male | red |
| 3 | contacts | 3 | male | red |
| 4 | contacts | 4 | female | green |
解决方案:两种高效实现方式
下面以「找所有联系人的 fav_colour 都是 'red' 的公司」为例,你可以根据实际需求替换字段和匹配条件(比如模糊匹配用 LIKE '%指定字符串%')。
方法1:GROUP BY + HAVING 统计匹配数
这种方法通过统计公司的总关联记录数,和符合条件的记录数,当两者相等时,说明所有记录都满足要求:
SELECT c.id, c.company_name FROM n_companies c JOIN n_contacts con ON c.id = con.company_id JOIN n_custom cu ON cu.custom_type = 'contacts' AND cu.custom_type_id = con.id GROUP BY c.id, c.company_name HAVING COUNT(*) = SUM(CASE WHEN cu.fav_colour = 'red' THEN 1 ELSE 0 END);
逻辑解释:
COUNT(*)统计当前公司下所有关联的自定义记录总数SUM(CASE...)统计其中符合指定条件的记录数- 只有当两者相等时,才能证明该公司的所有关联记录都包含指定字符串
方法2:NOT EXISTS 排除不符合的公司
这种方法逻辑更直观:直接找「不存在任何关联记录不符合条件」的公司:
SELECT c.id, c.company_name FROM n_companies c WHERE NOT EXISTS ( SELECT 1 FROM n_contacts con JOIN n_custom cu ON cu.custom_type = 'contacts' AND cu.custom_type_id = con.id WHERE con.company_id = c.id AND cu.fav_colour != 'red' -- 这里是"不满足条件"的判断 );
逻辑解释:
- 子查询会检查当前公司下是否存在一条关联记录不包含指定字符串
- 如果
NOT EXISTS这个子查询的结果,就说明该公司所有记录都符合要求
适配你的搜索UI三种模式
如果你的UI支持「任意/全部/无记录包含」三种搜索模式,可以基于上面的代码快速调整:
- 任意包含:把方法1的
HAVING COUNT(*) = SUM(...)改成HAVING SUM(...) > 0;或者把方法2的NOT EXISTS换成EXISTS,并把子查询里的条件改成「符合条件」 - 无记录包含:把方法1的
HAVING改成SUM(...) = 0;或者把方法2的子查询条件改成「符合条件」,保留NOT EXISTS
比如「无记录包含'red'」的查询:
SELECT c.id, c.company_name FROM n_companies c WHERE NOT EXISTS ( SELECT 1 FROM n_contacts con JOIN n_custom cu ON cu.custom_type = 'contacts' AND cu.custom_type_id = con.id WHERE con.company_id = c.id AND cu.fav_colour = 'red' );
内容的提问来源于stack exchange,提问作者SammyBlackBaron
相关产品推荐
相关产品推荐

