左连接变成内连接

19 sql

SELECT
a.foo
b.bar
c.foobar
FROM tableOne AS a
INNER JOIN tableTwo AS b ON a.pk = b.fk
LEFT JOIN tableThree AS c ON b.pk = c.fk
WHERE a.foo = 'something'
AND c.foobar = 'somethingelse'
Run Code Online (Sandbox Code Playgroud)

在where子句之后使用和子句似乎将左连接转换为内连接.我看到的行为是,如果tableThree中没有'somethingelse',将返回0行.

如果我将c.foobar ='somethingelse'移动到join子句中,则存储的连接将像左连接一样运行.

    SELECT
    a.foo
    b.bar
    c.foobar
    FROM tableOne AS a
    INNER JOIN tableTwo AS b ON a.pk = b.fk
    LEFT JOIN tableThree AS c ON b.pk = c.fk
    AND c.foobar = 'somethingelse'
    WHERE a.foo = 'something'
Run Code Online (Sandbox Code Playgroud)

有人能指出我描述为什么会发生这种情况的文件吗?非常感谢你

Dav*_*kle 46

这是因为你的WHERE条款.

无论何时在WHERE子句中指定左连接右侧的值(即NOT NULL),都必须消除所有NULL值,并且它实际上变为了INNER JOIN.

如果你写,AND (c.foobar = 'somethingelse' OR c.foobar IS NULL)那将解决问题.

您还可以将该c.foobar部分移动到连接谓词中,这也将解决问题.


Mar*_*n B 5

您看到这种情况的原因是因为左连接将c那些不存在的行的所有列设置为 NULL c(即无法连接的行)。这意味着比较c.foobar = 'somethingelse'不正确,这就是不返回这些行的原因。

在您将c.foobar = 'somethingelse'移入连接条件的情况下,当条件不为真时,该连接仍会返回这些行(尽管具有 NULL 值)。


小智 5

'where' 子句在连接之后执行。这对于内部联接并不重要,但对于外部联接很重要。

缩短示例

SELECT b.bar,c.foobar FROM tableTwo AS b LEFT JOIN tableThree AS c ON b.pk=c.fk WHERE c.foobar='somethingelse'

Raw data                  Outer Join Result        Select Result
b.pk c.fk c.foorbar       b.pk c.fk c.foorbar      c.foorbar
1    1    something       1    1    something      <not in result set>
1    1    somethingelse   1    1    somethingelse  somethingelse


SELECT b.bar,c.foobar FROM tableTwo AS b LEFT JOIN tableThree AS c ON b.pk=c.fk AND c.foobar='somethingelse'

Raw data                  Outer Join Result        Select Result
b.pk c.fk c.foorbar       b.pk c.fk c.foorbar      c.foorbar
1    1    something       1    null null           null
1    1    somethingelse   1    1    somethingelse  somethingelse
Run Code Online (Sandbox Code Playgroud)