我制作了一个脚本,它从交换机端口获取 mac 地址并将它们放入数据库中。我将它插入到导入表中,以便稍后复制到真实表中。一切都好。现在我正在编写查询以查找哪些 MAC 地址是新的。所以,我需要导入表中不在目标表中的行。左外连接是有意义的:
select *
from SwitchportMac_import i
left outer join SwitchportMac sm
on sm.switch = i.switch and sm.port = i.port and sm.mac = i.mac
这也返回i
匹配的行sm
。当然,我可以添加一个where sm.id is null
,但我大吃一惊。
所以要么:
- 我是个白痴,做了一些明显错误的事情
- 我是个白痴,20 年来一直在解释和理解加入错误
如果是第一个,我会转储 DDL 并弄清楚,但我害怕它是第二个。是否存在外部关键字只是为了让我感到困惑?
LEFT JOIN
并且LEFT OUTER JOIN
是同义词,所以很抱歉,但这听起来像选项2 :-)“外部”联接(保留不匹配的行)与“内部”(不保留)相反。
外连接有三种口味。Left、Right、Full(取决于要保留哪些不匹配的行)。
由于 SQL 没有任何其他类型的连接(例如左/右反半连接)的直接连接语法,因此允许
OUTER
关键字在语法中是可选的没有歧义。LEFT ANTI SEMI JOIN
听起来像您期望的LEFT OUTER
那样。您可以通过多种方式实现它。通常NOT EXISTS
是首选,但您可以LEFT OUTER JOIN
与 结合使用IS NULL
以仅保留不匹配的。这一切都在文档的“加入类型”部分得到确认
just周围的方括号
[OUTER]
表示这是可选的,但仍然适用相同的定义。这将是我获得所需内容的首选方式,使用带有 EXISTS 的相关子查询。假设您在交换机、端口和 mac 上的两个表上都有索引,这也应该是很好的性能。
正确的。这正是 LEFT [OUTER] JOIN 所做的——无论它能否在“右”表 (sm) 中找到匹配的行,它都能为您提供“左”表 (i) 中的所有内容。
要获得“新”项目(那些出现在“左”表中但不出现在“右”表中的项目),您还需要包括“为空”测试。这通常称为“排除连接”。
where sm.id is null
需要匹配连接中不存在的行。左连接总是
OUTER
委员会发明的语法糖。他们想提前让您和其他人感到困惑。你不是白痴,混乱是按计划实施的。LEFT join 说“从左边取出所有行,即前面的表,即 SwitchportMac_import”。您不需要该表中的所有行,只需要不匹配的行。
添加 IS NULL 将起作用。我认为 NOT EXISTS 会更好地满足您的需求。