Mysql 转弯抹角

Mysql get where not in with a twist

我想获取没有联系方式的公司 main_phone 或 phone 这是我的架构

Firms table
+----+-------+
| id | name  |
+----+-------+
|  1 | Firm1 |
|  2 | Firm2 |
|  3 | Firm3 |
+----+-------+

Contacts
+----+----------+---------+
| id |  label   | firm_id |
+----+----------+---------+
|  1 | Contact1 |       1 |
|  2 | Contact2 |       1 |
|  3 | Contact3 |       2 |
|  4 | Contact4 |       3 |
+----+----------+---------+

contact_methods
+----+-------------+------------+
| id | method_type | contact_id |
+----+-------------+------------+
|  1 | main_phone  |          1 |
|  2 | main_fax    |          1 |
|  3 | email       |          1 |
|  4 | main_fax    |          4 |
|  5 | main_fax    |          3 |
|  6 | phone       |          2 |
|  7 | main_mobile |          1 |
|  8 | url         |          4 |
+----+-------------+------------+

这是我的查询

SELECT 
firms.id
FROM firms 
JOIN contacts ON (contactable_id = firms.id)
JOIN contact_methods ON contacts.id = contact_methods.contact_id
WHERE 
firms.active = 1
AND
contact_methods.method_type NOT IN ('mobile','phone','main_mobile','main_phone')

我正在获取所有公司 :s

您的代码检查每个公司是否有 any 不属于列表的联系人类型 - 而您要确保 none 的公司联系人确实如此。

一个选项使用聚合:

select f.*
from firm f
left join contacts c on c.firm_id = f.id
left join contact_methods cm on cm.contact_id = c.id
group by f.id
having not max(cm.method_type in ('mobile','phone','main_mobile','main_phone')) <=> 1

或者,您可以使用 not exists:

select f.*
from firm f
where not exists (
    select 1
    from contacts c
    inner join contact_methods cm on cm.contact_id = c.id
    where c.firm_id = f.id and cm.method_type in ('mobile','phone','main_mobile','main_phone')
)
SELECT *
FROM firms
WHERE NOT EXIST ( SELECT NULL
                  FROM contacts
                  WHERE firms.id = contacts.firm_id )

contact_methods 此任务不需要。

如果您需要相同的联系人类型,请使用:

SELECT *
FROM firms
WHERE NOT EXIST ( SELECT NULL
                  FROM contacts
                  JOIN contact_methods ON contacts.id = contact_methods.contact_id 
                  WHERE firms.id = contacts.firm_id
                    AND contact_methods.method_type NOT IN ({types list}) )

i want just the firms.id that does not have a contact method in ('mobile','phone','main_mobile','main_phone')

SELECT *
FROM firms
WHERE NOT EXIST ( SELECT NULL
                  FROM contacts
                  JOIN contact_methods ON contacts.id = contact_methods.contact_id 
                  WHERE firms.id = contacts.firm_id
                    AND contact_methods.method_type IN ('mobile', 'phone', 'main_mobile', 'main_phone') )