我的查询似乎忽略了 left 表的LEFT JOIN
的ON column = constant
predicate ,但它确实对 right 表强制执行了ON column = constant
。
如果我将左表的ON column = constant
移到WHERE
子句,查询将按预期工作。
对于左表,我是将column = constant
放在查询的WHERE
部分,还是放在LEFT JOIN
的ON
子句中,这有什么关系呢?
(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
子句中,它会工作:
1条答案
按热度按时间zqdjd7g91#
LEFT [OUTER] JOIN
的ON
子句只规定是否连接右表中的0行或多行。(可能会使输出行相乘。)它不会 * 过滤左表中的行。如果你想这样做,表达式必须进入
WHERE
子句(正如你已经发现的那样)或[INNER] JOIN
的ON
子句。当然,
WHERE
条件使得同一个表上的LEFT JOIN
变得毫无意义,因为它现在被迫充当普通的JOIN
。这都是设计好的标准SQL