MySQl查询中的基本布尔逻辑

问题描述

有关详细信息,请参见this fiddle

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

以表格形式显示时,数据库如下所示(该结构的详细信息在小提琴中):

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表,因此正在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 |