我刚刚找到了一个包含Venn diagrams个不同联接的精彩页面以及执行它们的代码:
http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins
我在查询中使用了“Right Excluding Join”,维恩图看起来像这样:
这是代码:
SELECT subjects.subject
FROM sold_subjects
RIGHT JOIN subjects
ON sold_subjects.subject = subjects.subject
WHERE sold_subjects.subject IS NULL
我要求解释这段代码实际上做了什么,特别是最后一行发生了什么。我知道我们正在加入他们有相同主题的两个关系,但是当我们在最后一行中将其中一个关系的主题设置为NULL时会发生什么?
答案 0 :(得分:2)
JOIN
从两个表中获取信息,并根据您在ON
或WHERE
子句中指定的规则加入这些信息。
JOIN
修饰符,例如LEFT
,INNER
,OUTER
和RIGHT
可控制您JOIN
在以下情况下的行为不匹配的记录 - 当 A 中的记录根据指定的规则与 B 中的记录匹配时,反之亦然强>
要理解这一部分,请将表A作为左表,将表B作为右表。如果有多个连接,则每个连接中的右表是名称紧邻JOIN
命令的表。
例如 FROM a1 LEFT JOIN ... LEFT JOIN b
b
表是正确的,之前的任何表都是左表。
这是修饰语的摘要'行为:
LEFT
:保留左表中不匹配的记录,丢弃右表中的记录; RIGHT
:在右表中保留不匹配的记录,丢弃左表中的记录; INNER
:仅保留匹配的记录,从两个表中丢弃不匹配的记录; OUTER
或FULL
:保留所有记录,无论是否匹配。想象一下,你有两个简单的表,其名称与你放在那里的名称相同。
sold_subjects subjects
subject subject
1 1
2 4
3 5
4 6
当您RIGHT JOIN
两个表时,您创建第三个表,如下所示:
joined_table
sold_subjects.subject subjects.subject
1 1
4 4
NULL 5
NULL 6
请注意,此子集中的2
和3
主题已经消失。
当您使用WHERE
添加sold_subjects.subject IS NULL
子句时,您只保留最后两行主题不匹配。
答案 1 :(得分:2)
正确的联接可确保您保留正确表格的所有记录。如果与左表不匹配,则源自左表的结果中的所有变量都将为空(因为没有匹配)。
where子句检查lefttable.subject的值是否为null。如果它不为空,那么显然连接成功了。如果为null,则连接不起作用,将此值留空。因此,根据定义,这个where子句将返回左表中没有匹配的右表的所有记录,这正是维恩图所说的!
这是SQL中非常常见的做法,也有用例。例如:左表是销售,右表是客户,您想要了解所有没有销售的客户。
答案 2 :(得分:2)
RIGHT JOIN
是RIGHT OUTER JOIN
的简写
Consider the excellent explanation in the fine manual:
LEFT OUTER JOIN
返回合格笛卡尔积中的所有行 (即,通过其连接条件的所有组合行),加上一个副本 左侧表中没有右手的每一行 传递连接条件的行。这个左手行延伸到 通过插入空值来连接表的全宽度 右栏。请注意,只有JOIN
子句的条件是 在决定哪些行匹配时考虑。外面的条件 之后适用。相反,
RIGHT OUTER JOIN
会返回所有已连接的行以及一行 对于每个不匹配的右侧行(在左侧扩展为空)。 这只是一种符号方便,因为您可以将其转换为 通过切换左右表来LEFT OUTER JOIN
。
大胆强调我的。您的查询只是 一种 方式,可以排除另一个表中不存在的行,附加一个闪亮的热门词(" Right排除JOIN&#34 ; )。还有其他人:
现在,对于棘手的部分 - 或者你偏离原作的地方:
但是当我们在最后一行中将其中一个关系的主题设置为NULL时会发生什么?
您的查询有:
WHERE sold_subjects.subject IS NULL
原文说:
WHERE A.Key IS NULL
Key
应该暗示 NOT NULL
。如果基础表列sold_subjects.subject
或subjects.subject
中的任何一个可以为NULL,则查询只是不起作用。会有无法消除行符合条件的方式:
subjects.subject IS NULL
,sold_subjects.subject
subjects.subject IS NULL
以及sold_subjects.subject
subjects.subject IS NOT NULL
但sold_subjects
如果其中一个链接列可以为NULL,并且您希望将NULL值视为实际的值(它们不是),即匹配NULL NULL,您可以使用NULL-safe operator IS NOT DISTINCT FROM
替换为反连接:
SELECT s.subject
FROM subjects s
LEFT JOIN sold_subjects ss ON ss.subject IS NOT DISTINCT FROM s.subject
WHERE ss.subject IS NULL;
语法较短,使用较常用的LEFT JOIN
,但其他方面相同。 IS NOT DISTINCT FROM
通常比简单的=
慢,只能在需要的地方使用它。通常,您在defined NOT NULL
的关键列上连接表 - 隐式地(PK列自动为NOT NULL
)或显式连接。