SQL 具有多个条件的 WHERE 语句
SQL WHERE statement with multiple conditions
我有电影、演职员表、人物和角色table(下)我想找到既是演员又是导演的人的名字。
电影(TABLE)
id int
title
学分(TABLE)
id int
movie_id int
person_id int
role_id int
人(TABLE)
id int
name
角色(TABLE)
id int
role (Actor, Director)
这就是我所做的:
SELECT p.name, r.role, m.role_id
FROM mtm_credits m
JOIN people p ON p.id = m.person_id
JOIN roles r ON r.id = m.role_id
WHERE role = 'Director' AND role = 'Actor';
但是,我得到 0 个结果。任何建议表示赞赏。
我想你想要聚合:
SELECT p.name
FROM mtm_credits m JOIN
people p
ON p.id = m.person_id JOIN
roles r
ON r.id = m.role_id
WHERE r.role IN ('Director', 'Actor')
HAVING COUNT(DISTINCT r.role) = 2;
您的查询的问题是您正在搜索一个既是导演又是演员的角色:两个条件不能同时为真,因此查询为空。
每当您需要查看多行时,就会想到聚合:
SELECT p.*
FROM mtm_credits m
JOIN people p ON p.id = m.person_id
JOIN roles r ON r.id = m.role_id
WHERE r.role IN ('Director', 'Actor')
GROUP BY p.id
HAVING COUNT(DISTINCT r.role) = 2
这将搜索导演 或 演员,然后按人物对行进行分组;最后,having
子句只允许同时具有这两种角色的人。
问题是结果 table 中没有一行 'role' 既是 'Director' 又是 'Actor',因为 'role' 只能是一个值。
首先考虑您的 table 加入后的样子是很有用的。在这种情况下,您有:
credits.id, credits.movie_id, credits.person_id, credits.role_id, person.id, person.name, role.id, role.name
现在一个既是导演又是演员的人在这个table中会有两行,像这样:
| credits.id | credits.movie_id | credits.person_id | credits.role_id | person.id | person.name | role.id | role.name |
| 111 | 222 | 333 | 444 | 555 | 333 | N. Cage | 555 | Actor |
| 111 | 222 | 333 | 444 | 555 | 333 | N. Cage | 555 | Director |
正如其他人所说,您需要执行聚合以便一行可以有多个角色值,或者您可以获取结果并在外部进行过滤
有两个答案使用相同的方法,但都是错误的。如果这个假设的数据库只包含每个人一部电影,那么它就会成功。如果有多部电影引用了 people
记录,或者如果 credits
引用了单个 people
记录并加入了 roles
的 roles
记录。role
= 'Director' 或 roles
.role
= 'Actor`,此查询 returns 该无效结果的记录。这会破坏指定的行为。
请注意,@Jason-Chen 解释了您在查询时遇到的问题,而我特别反对这两个答案与 posting-time.
时给出的解决方案
与其简单地计算结果以保证每个 people.id 有多个角色,这是上述两个示例给出的唯一保证,管理员应该查询同时存在于列表中的连接'Director' 是 roles.role 值的所有角色记录和 'Actor' 是 roles.role 值的所有记录。
请注意,我在下面使用了不同的名称,因为我通常发现 single-letter 别名的做法很糟糕,我希望教师能向新学生灌输更好的做法。此外,我发现 table 单数形式的名称产生最易读的代码。
select `person`.*
from `people` `person`
where `person`.`id` in (
select `credit`.`person_id`
from `roles` `role`
join`credits` `credit`
on `role`.`id` = `credit`.`role_id`
where `role` like "Director"
) and `person`.`id` in (
select `credit`.`person_id`
from `roles` `role`
join`credits` `credit`
on `role`.`id` = `credit`.`role_id`
where `role` like "Actor"
);
我从角色 table 的两个 sub-queries 中选择一个值,它不需要别名,而是作为一个集合。这会导致非常快速的查找,即使对于相当大的 tables,前提是所使用的键在连接的两侧都有索引。
此外,这比连接更好,因为给出现实生活中的例子,例如“基努·里维斯”、“梅尔·吉布森”、“汤姆·克鲁斯”或其他拥有许多 Director/Actor 电影的名人,每个这样的记录都会导致结果集放大,其中数据中的单个添加记录会导致多个结果记录。
我有电影、演职员表、人物和角色table(下)我想找到既是演员又是导演的人的名字。
电影(TABLE)
id int
title
学分(TABLE)
id int
movie_id int
person_id int
role_id int
人(TABLE)
id int
name
角色(TABLE)
id int
role (Actor, Director)
这就是我所做的:
SELECT p.name, r.role, m.role_id
FROM mtm_credits m
JOIN people p ON p.id = m.person_id
JOIN roles r ON r.id = m.role_id
WHERE role = 'Director' AND role = 'Actor';
但是,我得到 0 个结果。任何建议表示赞赏。
我想你想要聚合:
SELECT p.name
FROM mtm_credits m JOIN
people p
ON p.id = m.person_id JOIN
roles r
ON r.id = m.role_id
WHERE r.role IN ('Director', 'Actor')
HAVING COUNT(DISTINCT r.role) = 2;
您的查询的问题是您正在搜索一个既是导演又是演员的角色:两个条件不能同时为真,因此查询为空。
每当您需要查看多行时,就会想到聚合:
SELECT p.*
FROM mtm_credits m
JOIN people p ON p.id = m.person_id
JOIN roles r ON r.id = m.role_id
WHERE r.role IN ('Director', 'Actor')
GROUP BY p.id
HAVING COUNT(DISTINCT r.role) = 2
这将搜索导演 或 演员,然后按人物对行进行分组;最后,having
子句只允许同时具有这两种角色的人。
问题是结果 table 中没有一行 'role' 既是 'Director' 又是 'Actor',因为 'role' 只能是一个值。
首先考虑您的 table 加入后的样子是很有用的。在这种情况下,您有:
credits.id, credits.movie_id, credits.person_id, credits.role_id, person.id, person.name, role.id, role.name
现在一个既是导演又是演员的人在这个table中会有两行,像这样:
| credits.id | credits.movie_id | credits.person_id | credits.role_id | person.id | person.name | role.id | role.name |
| 111 | 222 | 333 | 444 | 555 | 333 | N. Cage | 555 | Actor |
| 111 | 222 | 333 | 444 | 555 | 333 | N. Cage | 555 | Director |
正如其他人所说,您需要执行聚合以便一行可以有多个角色值,或者您可以获取结果并在外部进行过滤
有两个答案使用相同的方法,但都是错误的。如果这个假设的数据库只包含每个人一部电影,那么它就会成功。如果有多部电影引用了 people
记录,或者如果 credits
引用了单个 people
记录并加入了 roles
的 roles
记录。role
= 'Director' 或 roles
.role
= 'Actor`,此查询 returns 该无效结果的记录。这会破坏指定的行为。
请注意,@Jason-Chen 解释了您在查询时遇到的问题,而我特别反对这两个答案与 posting-time.
时给出的解决方案与其简单地计算结果以保证每个 people.id 有多个角色,这是上述两个示例给出的唯一保证,管理员应该查询同时存在于列表中的连接'Director' 是 roles.role 值的所有角色记录和 'Actor' 是 roles.role 值的所有记录。
请注意,我在下面使用了不同的名称,因为我通常发现 single-letter 别名的做法很糟糕,我希望教师能向新学生灌输更好的做法。此外,我发现 table 单数形式的名称产生最易读的代码。
select `person`.*
from `people` `person`
where `person`.`id` in (
select `credit`.`person_id`
from `roles` `role`
join`credits` `credit`
on `role`.`id` = `credit`.`role_id`
where `role` like "Director"
) and `person`.`id` in (
select `credit`.`person_id`
from `roles` `role`
join`credits` `credit`
on `role`.`id` = `credit`.`role_id`
where `role` like "Actor"
);
我从角色 table 的两个 sub-queries 中选择一个值,它不需要别名,而是作为一个集合。这会导致非常快速的查找,即使对于相当大的 tables,前提是所使用的键在连接的两侧都有索引。
此外,这比连接更好,因为给出现实生活中的例子,例如“基努·里维斯”、“梅尔·吉布森”、“汤姆·克鲁斯”或其他拥有许多 Director/Actor 电影的名人,每个这样的记录都会导致结果集放大,其中数据中的单个添加记录会导致多个结果记录。