我正在阅读一本关于外连接的SQL书,并说:
从连接的非保留侧到过滤器的哪个属性的选择很重要。您应该选择一个属性,当该行是外行时,该属性只能为NULL,否则不会(例如,不是源自基表的NULL)。为此,可以考虑三种情况 - 主键列,连接列和定义为NOT NULL的列。主键列不能为NULL;因此,这样一列中的NULL只能表示该行是外行。如果连接列中的行具有NULL,则该行将被连接的第二阶段过滤掉,因此这样的列中的NULL只能表示它是外部行。显然,定义为NOT NULL的列中的NULL只能表示该行是外行。下面是代码示例
Sales.Orders有一个shippingid列,可以为null,所以如果我这样做:
SELECT C.custid, C.companyname
FROM Sales.Customers AS C
LEFT OUTER JOIN Sales.Orders AS O
ON C.custid = O.custid
WHERE O.shippingid IS NULL;
它产生相同的结果,那么为什么选择过滤哪个属性很重要呢?
可以用一些样本数据来解释。假设这是没有WHERE子句的LEFT JOIN查询的结果:
+----------+------------+-----------+----------+-----------+--------------+
| c.custid | c.custname | o.orderid | o.custid | o.notnull | o.shippingid |
+----------+------------+-----------+----------+-----------+--------------+
| 1 | John | 11 | 1 | 1 | 101 |
| 1 | John | 12 | 1 | 1 | 102 |
| 2 | Jack | NULL | NULL | NULL | NULL |
| 3 | Jane | 13 | 3 | 1 | NULL |
+----------+------------+-----------+----------+-----------+--------------+
假设你知道LEFT JOIN是如何工作的,你会发现John有2个订单,Jack有0个,Jane有1个。注意:
因此,如果您要在左表中找到右表中没有匹配记录的行,则需要检查主键,连接列或非空列是否为NULL。检查可空列为NULL将简单地给出误报,就像上面的示例中Jane有(未发货)订单一样。
如果你使用LEFT JOIN
测试不存在(而不是NOT EXISTS
),那么使用JOIN
键:
SELECT C.custid, C.companyname
FROM Sales.Customers C LEFT OUTER JOIN
Sales.Orders O
ON C.custid = O.custid
WHERE O.custId IS NULL;
因为这是一个JOIN
键,你知道NULL
值意味着没有匹配。
这基本上是该段落试图说的。
或者,您可以使用主键。我想不出使用任何其他专栏的好理由,所以我只推荐一个JOIN
密钥或主键。并且说,对于任何其他列,即使行匹配,也存在列本身可能是NULL
的风险。