我的印象是
SELECT *
FROM TableA a
LEFT JOIN TableB b ON a.ID = b.AID AND b.SomeString <> 'ABC'
和
SELECT *
FROM Table a
LEFT JOIN TableB b ON a.ID = b.AID
WHERE b.AID IS NULL OR b.SomeString <> 'ABC'
会产生相同的结果。
不幸的是,在我的情况下,他们不是:-(
他们可能没有任何理由?
答案 0 :(得分:4)
表A
+----+
| ID |
+----+
| 1 |
| 2 |
| 3 |
+----+
表B
+-----+-----------------+
| AID | SomeString |
+-----+-----------------+
| 1 | SomeOtherString |
| 2 | ABC |
+-----+-----------------+
SELECT *
FROM TableA a
LEFT JOIN TableB b
ON a.ID = b.AID
AND b.SomeString <> 'ABC'
这会将A
的每一行与B
匹配a.ID = b.AID AND b.SomeString <> 'ABC'
的每一行联接起来。如果与A中的行匹配的行数为零,那么对于表NULL
中的列,B
的结果将保留(如下面的Id = 2所示 - 与id匹配的单行&#39 ; t满足第二个条件,Id = 3,其中甚至没有与id匹配的行
+----+------+-----------------+
| ID | AID | SomeString |
+----+------+-----------------+
| 1 | 1 | SomeOtherString |
| 2 | NULL | NULL |
| 3 | NULL | NULL |
+----+------+-----------------+
SELECT *
FROM TableA a
LEFT JOIN TableB b ON a.ID = b.AID
这稍微改变了语义,因为现在被认为是匹配只需要满足id
谓词而不是字符串条件。带有ids 2和3的A中的行与此新匹配条件下的B中的行匹配,并且只有id = 3被外部联接添加回来。
+----+------+-----------------+
| ID | AID | SomeString |
+----+------+-----------------+
| 1 | 1 | SomeOtherString |
| 2 | 2 | ABC |
| 3 | NULL | NULL |
+----+------+-----------------+
SELECT *
FROM TableA a
LEFT JOIN TableB b
ON a.ID = b.AID
WHERE b.AID IS NULL
OR b.SomeString <> 'ABC'
这将在Query 1.5结果中显示的行上运行WHERE b.AID IS NULL OR b.SomeString <> 'ABC
谓词。离开你两行。外连接保留的行是其中之一。
+----+------+-----------------+
| ID | AID | SomeString |
+----+------+-----------------+
| 1 | 1 | SomeOtherString |
| 3 | NULL | NULL |
+----+------+-----------------+
答案 1 :(得分:3)
由于NULL逻辑。
在第一个查询中,您获得A中的所有行,仅当键与和匹配时才会在B上连接.S.SomeString不等于ABC。如果b.SomeString为null,那么如果找不到该键,则会得到…and NULL is not equal to ABC
。根据NULL比较的规则,将NULL与任何“失败”进行比较,例如NULL <> ‘ABC’
等同于假。最终结果:如果找不到ID,则b.SomeString为NULL,并从返回的集合中丢弃该行。
在第二个查询中,您将获得A中的所有行,仅当键匹配时才连接到B.并且只有 表之后才会评估where子句。它(基本上)表示保持 ID与或不匹配的行.S.SomeString&lt;&gt; “ABC”(如上所述,将排除NULL)。因此,您最终得到ID不匹配的行,和行匹配b.SomeSting不是ABC的行。
这些东西可能很难理解,难以解释,而且很难在没有样本数据的情况下解释 - 这就是我说你应该查看一些问题,直到你了解它是如何工作的。