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 |
详情见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 |