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

时间:2012-12-04 09:44:21

标签: sql postgresql left-join

SQL 左连接查询忽略 left 表上的ON column = constant谓词。
但是,它关心 right 表中的另一个ON column = constant谓词。

如果我将左表的ON column = constant移动到WHERE子句,则查询将按预期工作。

对于左表,如果我将column = constant放在查询的WHERE部分中,或者放在查询的JOIN ... ON部分中,为什么重要?

(会发生什么,左表ON column = constant条件被推到“JOIN过滤器”步骤,似乎被忽略了。)

详细信息:

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过滤器”步骤,而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'的“加入过滤器”不能过滤出规范不是'C'的行?它没有。)

(PostgreSQL版本psql (9.1.6, server 9.1.1)。)

以下是指向类似查询的链接,但如果您将左表ON column = constant移动到where子句,则答案不会解释为什么它会起作用: Add condition while using LEFT OUTER JOIN

1 个答案:

答案 0 :(得分:3)

关键是ON的{​​{1}}子句仅规定是否连接了右表中的一行。

从左表中过滤行。如果你想这样做,表达式必须进入LEFT [OUTER] JOIN子句(正如你已经发现的那样)或WHERE的{​​{1}}子句。
这都是设计的。