加入谓词和比较运算符

时间:2019-07-12 22:15:28

标签: 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

虽然我可以 kinda 看看not-equals(!=)运算符将如何返回此结果,但却引出了一个问题,即连接谓词中哪种比较类型有用哪些不是-联接类型[内部,右侧,左侧...]是否会对返回结果产生不利影响,或者联接类型和比较是否可以解析为可操作的行为(换句话说,它始终必须为== )?另外,如果有任何资源可以帮助我,那将很棒。谢谢。

1 个答案:

答案 0 :(得分:3)

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

因此,如果一个表具有n行,其他表具有m行,则笛卡尔乘积具有n * m行。

on子句过滤这些行。平等是最常见的过滤器,此类联接通常称为等联接。它们提供了最多的优化机会,并且通常是最有效的。

(外部联接是类似的,但是具有一种机制来包括不匹配的行。)

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

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

在您的情况下,通常是not exists。要查找性别不在参考表中的员工:

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

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