左表的 LEFT JOIN 的连接条件似乎被忽略了?

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

我的查询似乎忽略了

left
表的
ON column = constant
LEFT JOIN 谓词。不过,它确实对
right
表强制执行 ON column = constant

如果我将左表的

ON column = constant
移至
WHERE
子句,则查询将按预期工作。

对于左表,我是否将

column = constant
放在查询的
WHERE
部分,还是放在
ON
LEFT JOIN
子句中,这很重要吗?

(发生的情况是,左表

ON column = constant
条件被推到“JOIN Filter”步骤,在该步骤中它似乎被忽略了。)

详情:

EXPLAIN ANALYZE
select * from DW1_PAGE_PATHS t left join DW1_PAGES g
   on t.TENANT = g.TENANT
  and t.PAGE_ID = g.GUID
  and g.GUID = 'abcdefg'  -- works
  and t.CANONICAL = 'C'  -- "ignored", unless moved to `where` clause
where t.TENANT = '72'
  and PARENT_FOLDER like '/%';

这里(下)是执行计划。请注意,

t.CANONICAL = 'C'
已被推到“JOIN Filter”步骤,而
g.GUID = 'abcdefg'
过滤器在扫描右表时直接发生。

 Nested Loop Left Join  (cost=... actual time=...)
   Join Filter: (((t.canonical)::text = 'C'::text)
             AND ((t.tenant)::text = (g.tenant)::text)
             AND ((t.page_id)::text = (g.guid)::text))
   ->  Seq Scan on dw1_page_paths t
         Filter: (((parent_folder)::text ~~ '/%'::text)
              AND ((tenant)::text = '72'::text))
   ->  Seq Scan on dw1_pages g
         Filter: (((tenant)::text = '72'::text)
              AND ((guid)::text = 'abcdefg'::text))

(另一个问题:为什么“加入过滤器”与 t.canonical = 'C' 不会过滤掉 canonical 不是 'C' 的行?它不会。)

PostgreSQL 版本:

psql (9.1.6, server 9.1.1)

这里是类似查询的链接,但答案没有解释为什么,如果您将左表

ON column = constant
移动到
where
子句,它会起作用:

sql postgresql left-join
1个回答
5
投票

ON
LEFT [OUTER] JOIN
子句仅规定是否连接右表中的 0 或更多行。 (可能会增加输出行。)

过滤左表中的行。如果您想要这样,表达式必须进入

WHERE
子句(正如您已经发现的那样)或
ON
[INNER] JOIN
子句。

当然,

WHERE
条件会使同一张表上的
LEFT JOIN
变得毫无意义,因为它现在被迫充当普通的
JOIN

这都是设计使然。

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