MySQl 查询中的基本布尔逻辑

Basic boolean logic in a MySQl query

详情见this fiddle

基本上,我正在一个非常基本的测试数据库中搜索 3 家公司之一的工作:BAe、Thales 和 Google。

数据库以表格形式显示时如下所示(结构的完整详细信息在 fiddle 中):

Candidate name  Company Job year    Skills
One             Thales  2015        C
One             BAe     2016        Python
One             Google  2017        C++
Two             BAe     2015        C++
Two             Google  2020        Python
Two             Thales  2019        C++, UML
Three           Google  2019        Python

我正在尝试各种查询来查找谁曾在哪些公司工作(技能与此问题无关)。

这个查询:

SELECT DISTINCT candidate_id FROM jobs j
WHERE 1=1
AND ( EXISTS (
             SELECT * FROM companies c
             WHERE c.company_id = j.company_id
             AND UPPER(c.company_name) LIKE 'THALES'));

正确给出:

+--------------+
| candidate_id |
+--------------+
|            1 |
|            3 |
+--------------+
2 rows in set (0.00 sec)

和这个查询:

SELECT DISTINCT candidate_id FROM jobs j 
WHERE 1=1 
AND ( EXISTS (
             SELECT * FROM companies c 
             WHERE c.company_id = j.company_id 
             AND UPPER(c.company_name) LIKE 'GOOGLE'));

正确给出

+--------------+
| candidate_id |
+--------------+
|            1 |
|            2 |
+--------------+
2 rows in set (0.00 sec)

但是,当我尝试合并时,要找到一位曾在 Thales 和 Google 工作过的候选人,我希望得到候选人 1,但结果却是空的:

SELECT DISTINCT candidate_id FROM jobs j 
WHERE 1=1 
AND ( EXISTS ( 
             SELECT * FROM companies c 
             WHERE c.company_id = j.company_id 
             AND UPPER(c.company_name) LIKE 'THALES') 
 AND  EXISTS ( 
             SELECT * FROM companies c 
             WHERE c.company_id = j.company_id 
             AND UPPER(c.company_name) LIKE 'GOOGLE') 
);

Empty set (0.00 sec)

最后一个查询有什么问题?

您正在搜索 jobs table,因此您正在寻找 Thales 和 Google 的工作,然后为这些工作选择所有不同的候选人。

由于一份工作(在您的数据模型中)仅在一家公司,因此没有工作可以匹配,因此不会返回任何候选人。

下面的查询会给出你想要的:

select * from candidates c
where 1=1
and ( exists (
  select * from jobs j
  where j.candidate_id = c.candidate_id
  and (exists (select * from companies com where com.company_id = j.company_id and upper(com.company_name) like 'THALES'))
))
and ( exists (
  select * from jobs j
  where j.candidate_id = c.candidate_id
  and (exists (select * from companies com where com.company_id = j.company_id and upper(com.company_name) like 'GOOGLE'))
));

我会说这是一个在 HAVING 子句中过滤的聚合查询。

select candidate_id
from jobs j
inner join companies c on c.company_id = j.company_id
where c.company_name in ('Thales', 'Google')        -- either one or the other
group by candidate_id
having min(j.company_id) <> max(j.company_id)       -- both match

your db fiddle 中,这会产生:

| candidate_id |
| -----------: |
|            1 |