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

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

SQL left join 查询会忽略

left
表上的 ON column = constant 谓词。
然而,它关心
right
表上的另一个 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 '/%';

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

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
子句,它会起作用: 使用 LEFT OUTER JOIN 时添加条件

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.