为了更好地理解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(!=)运算符将如何返回此结果,但却引出了一个问题,即连接谓词中哪种比较类型有用哪些不是-联接类型[内部,右侧,左侧...]是否会对返回结果产生不利影响,或者联接类型和比较是否可以解析为可操作的行为(换句话说,它始终必须为== )?另外,如果有任何资源可以帮助我,那将很棒。谢谢。
答案 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)
当然,如果您使用主键来引用表并包含适当的外键声明,则这样的查询将是不必要的。