mysql - 加入谓词和比较运算符

标签 mysql sql sql-server

为了更好地理解 SQL 连接的工作原理,我在理解查询返回的结果集时遇到了困难——我使用的表是:

员工

Id  Name    Salary  Gender  City
1   Sam     2500    Male    London
5   Todd    3100    Male    Toronto
3   John    4500    Male    New York
6   Jack    7000    Male    Shangri La
4   Sara    5500    Female  Tokyo
2   Pam     6500    Female  Sydney

和性别:

ID  Gender
1   Male
2   Female
3   Unknown

第一个查询返回性别列上内部联接的所有列 -

SELECT *
FROM Employees
INNER JOIN Gender
ON Employees.Gender = Gender.Gender

返回结果-

Id  Name    Salary  Gender  City        ID  Gender
1   Sam     2500    Male    London      1   Male
5   Todd    3100    Male    Toronto     1   Male
3   John    4500    Male    New York    1   Male
6   Jack    7000    Male    Shangri La  1   Male
4   Sara    5500    Female  Tokyo       2   Female
2   Pam     6500    Female  Sydney      2   Female

这几乎是我所期望的。但是,当我更改比较运算符时 -

SELECT *
FROM Employees
INNER JOIN Gender
ON Employees.Gender != Gender.Gender

我原本以为会返回一个空集,返回了这个——

Id  Name    Salary  Gender  City        ID  Gender
4   Sara    5500    Female  Tokyo       1   Male
2   Pam     6500    Female  Sydney      1   Male
1   Sam     2500    Male    London      2   Female
5   Todd    3100    Male    Toronto     2   Female
3   John    4500    Male    New York    2   Female
6   Jack    7000    Male    Shangri La  2   Female
1   Sam     2500    Male    London      3   Unknown
5   Todd    3100    Male    Toronto     3   Unknown
3   John    4500    Male    New York    3   Unknown
6   Jack    7000    Male    Shangri La  3   Unknown
4   Sara    5500    Female  Tokyo       3   Unknown
2   Pam     6500    Female  Sydney      3   Unknown

虽然我可以有点看到不等于 (!=) 运算符将如何返回此结果,但它回避了以下问题:哪种类型的比较在连接谓词中有用哪些不是 - 连接类型 [inner, right, left...] 是否会对返回的结果产生不利影响,或者连接类型和比较是否可以解析为可操作的行为(换句话说,它是否总是必须 == )?另外,如果有任何资源可以帮助我,那就太好了。谢谢。

最佳答案

内部联接是两个表的笛卡尔积的子集。也就是说,一个表中的每一行都与另一个表中的每一行配对。

因此,如果一个表有 n 行,另一个表有 m 行,则笛卡尔积有 n * m 行。

on 子句过滤这些行。相等性是最常见的过滤器,此类连接通常称为等值连接。它们提供最多的优化机会,通常效率最高。

(外连接类似,但有一种机制来包含不匹配的行。)

通常,join 谓词至少包含一个相等比较(尽管这不是必需的)。其他比较——包括使用 exists/in 的子查询——是允许的并且通常很有用。

任何体面的文档或教程或书籍都应该能够解释这一点。

在您的情况下,不存在 通常是意图。查找性别不在引用表中的员工:

SELECT e.*
FROM Employees e
WHERE NOT EXISTS (SELECT 1 FROM Gender g WHERE e.Gender = g.Gender)

当然,如果您使用主键引用表并包含适当的外键声明,则这样的查询是不必要的。

关于mysql - 加入谓词和比较运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57014569/

相关文章:

php - 如何使用php在html表中的每一行中找到最小值

MySQL - UNION ALL 查询 - 未知列错误

c# - 如何获取 Sql Server 数据库中所有模式的列表

mysql - 查找当年晚于今天发生的年度事件(生日日期)

mysql - SQL like 和 concat 不返回值

sql - 在不在投影中的字段上按 sql 排序

php - 如何对 MySQL 数据库中的行进行排序

sql-server - 从 SELECT 创建数据库名称

sql-server - Microsoft.SqlServer.ManagedDTS.dll SQL Server 2016 位置

mysql - 从 MySQL 查询返回第 n 条记录