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