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

kninwzqo  于 2024-01-07  发布在  PostgreSQL
关注(0)|答案(1)|浏览(155)

我的查询似乎忽略了 left 表的LEFT JOINON column = constant predicate ,但它确实对 right 表强制执行了ON column = constant
如果我将左表的ON column = constant移到WHERE子句,查询将按预期工作。
对于左表,我是将column = constant放在查询的WHERE部分,还是放在LEFT JOINON子句中,这有什么关系呢?
(What发生的情况是,左表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 '/%';

字符串
下面是exec计划。注意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子句中,它会工作:

zqdjd7g9

zqdjd7g91#

LEFT [OUTER] JOINON子句只规定是否连接右表中的0行或多行。(可能会使输出行相乘。)
它不会 * 过滤左表中的行。如果你想这样做,表达式必须进入WHERE子句(正如你已经发现的那样)或[INNER] JOINON子句。
当然,WHERE条件使得同一个表上的LEFT JOIN变得毫无意义,因为它现在被迫充当普通的JOIN
这都是设计好的标准SQL

相关问题