SQL / PostgreSQL 左连接忽略左表上的“on = constant”谓词

Kaj*_*nus 4 sql postgresql left-join

SQL左连接查询忽略ON column = constant上的谓词。 但是,它关心表上的另一个谓词。
ON column = constant

如果我将左表移动ON column = constant到 WHERE 子句,则查询将按预期工作。

对于左表,如果我将 放在column = constant查询的 WHERE 部分或查询的 JOIN ... ON 部分,这有什么关系?

(发生的情况是,左表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 '/%';
Run Code Online (Sandbox Code Playgroud)

这里(下面)是执行计划。请注意,t.CANONICAL = 'C'已被推到“加入过滤器”步骤,而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))
Run Code Online (Sandbox Code Playgroud)

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

(PostgreSQL 版本psql (9.1.6, server 9.1.1)。)

这是一个类似查询的链接,但如果您将左表移到子句中,答案并没有解释为什么它会起作用: Add condition while using LEFT OUTER JOINON column = constantwhere

Erw*_*ter 5

关键是ONa LEFT [OUTER] JOINonly的子句规定是否连接来自右表的行。

不是左表过滤行。如果你想这样做,表达式必须进入一个WHERE子句(正如你已经发现的那样)或 a 的ON子句[INNER] JOIN
这都是设计的。