我的查询似乎忽略了
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
子句,它会起作用:
ON
的
LEFT [OUTER] JOIN
子句仅规定是否连接右表中的 0 或更多行。 (可能会增加输出行。)
它不过滤左表中的行。如果您想要这样,表达式必须进入
WHERE
子句(正如您已经发现的那样)或 ON
的 [INNER] JOIN
子句。
当然,
WHERE
条件会使同一张表上的LEFT JOIN
变得毫无意义,因为它现在被迫充当普通的JOIN
。
这都是设计使然。