PostgreSQL应该离开联接使用WHERE或ON就足够了吗?

时间:2019-07-03 16:41:49

标签: postgresql

在执行选择子查询时,应该在其中使用WHERE还是“ s on s.id = t.id”就足够了?我想了解子查询是否不选择所有行,然后对其进行过滤,或者仅选择匹配条件“在add.id = table.id上”

SELECT * FROM table 
      left join (
          select *
          from add
          /* where add.id = 1 */ - do i need this?
          group by add.id
          ) add on add.id = table.id
    WHERE table.id = 1

据我从解释中了解到的:

Nested Loop Left Join  (cost=2.95..13.00 rows=10 width=1026)
Join Filter: (add.id = table.id)

它将加载所有行,然后执行过滤器。不好吗?

1 个答案:

答案 0 :(得分:1)

我不确定您的示例是否太简单了,但是您根本不需要为此子查询-绝对不是分组依据。

假设您确实需要一个子查询,那么对于此特定示例,无论是否添加where子句,它都会导致完全相同的查询计划。查询计划程序的想法是,它试图找到一种使查询尽可能快的方法。通常,这意味着以这种方式对联接和where子句的执行进行排序,以使结果集早于而不是晚于增加。我只使用import QtQuick 2.5 import QtQuick.Window 2.0 Window { visible: true height: 400 width: 675 Rectangle { anchors.fill: parent color: "cyan" Flex { height: parent.height width: parent.width flexDirection: "row" flexWrap: "wrap" justifyContent: "spaceAround" alignItems: "center" alignSelf: "center" alignContent: "stretch" Rectangle { color: "green"; height: 150; width: 150 } Rectangle { color: "green"; height: 150; width: 150 } Rectangle { color: "green"; height: 150; width: 150 } Rectangle { color: "green"; height: 150; width: 150 } Rectangle { color: "green"; height: 150; width: 150 } Rectangle { color: "green"; height: 150; width: 150 } Rectangle { color: "green"; height: 150; width: 150 } } } } reservations生成了完全相同的查询,希望可以。

customers
EXPLAIN
SELECT *
FROM reservations
  LEFT OUTER JOIN (
    SELECT *
    FROM customers
  ) AS customers ON customers.id = reservations.customer_id
WHERE customer_id = 1;

最深的箭头首先执行。这意味着即使我的子查询中没有Nested Loop Left Join (cost=0.17..183.46 rows=92 width=483) Join Filter: (customers.id = reservations.customer_id) -> Index Scan using index_reservations_on_customer_id on reservations (cost=0.09..179.01 rows=92 width=255) Index Cond: (customer_id = 1) -> Materialize (cost=0.08..4.09 rows=1 width=228) -> Index Scan using customers_pkey on customers (cost=0.08..4.09 rows=1 width=228) Index Cond: (id = 1) 的等效项,它仍然知道等式where add.id = 1应该为真,因此它决定在customers.id = customer_id = 1之前进行过滤尝试加入任何东西