选择从连接的非保留侧过滤哪个属性

问题描述 投票:0回答:2

我正在阅读一本关于外连接的SQL书,并说:

从连接的非保留侧到过滤器的哪个属性的选择很重要。您应该选择一个属性,当该行是外行时,该属性只能为NULL,否则不会(例如,不是源自基表的NULL)。为此,可以考虑三种情况 - 主键列,连接列和定义为NOT NULL的列。主键列不能为NULL;因此,这样一列中的NULL只能表示该行是外行。如果连接列中的行具有NULL,则该行将被连接的第二阶段过滤掉,因此这样的列中的NULL只能表示它是外部行。显然,定义为NOT NULL的列中的NULL只能表示该行是外行。下面是代码示例enter image description here enter image description here

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;

它产生相同的结果,那么为什么选择过滤哪个属性很重要呢?

sql
2个回答
1
投票

可以用一些样本数据来解释。假设这是没有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个。注意:

  • 如果没有匹配的订单,那么属于orders表的所有列都是NULL
  • 如果存在匹配的顺序,则可以在可空列中使用NULL

因此,如果您要在左表中找到右表中没有匹配记录的行,则需要检查主键,连接列或非空列是否为NULL。检查可空列为NULL将简单地给出误报,就像上面的示例中Jane有(未发货)订单一样。


1
投票

如果你使用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的风险。

© www.soinside.com 2019 - 2024. All rights reserved.