仅当先前的连接找不到任何内容时,左连接

时间:2019-03-28 14:33:21

标签: sql postgresql performance

我正尝试将其最小化。

-

比方说,我有三个表,即table1 table2和table3。所有这些表都有一个列“ organizationID”。我还有一个table0,它以某种方式链接到所有这些。

有时,“ organizationID”在表1中,有时在表2中,有时在表3中。

-

我正在做这样的事情:

SELECT coalesce(table1.organizationID,coalese(table2.organizationID,coalesce(table3.organizationID,0)))
FROM table0
LEFT JOIN table1 ON (some condition)
LEFT JOIN table2 ON (some condition)
LEFT JOIN table3 ON (some condition)

这有效。它给了我我想要的。问题在于性能。数据库始终执行所有三个联接,即使table1已经具有orgaizationID。

-

我想将此选择修改为以下内容:

SELECT coalesce(table1.organizationID,coalese(table2.organizationID,coalesce(table3.organizationID,0)))
FROM table0
LEFT JOIN table1 ON (some condition)
LEFT JOIN table2 ON (some condition) AND table1.organizationID IS NULL
LEFT JOIN table3 ON (some condition) AND table2.organizationID IS NULL

问题在于它仍在执行所有联接,因此花费相同的时间来完成执行。

如果成功实现以前的联接,是否有任何方法可以阻止联接运行?

-

非常感谢。

-

编辑:table3联接需要很多时间才能执行。我对此无能为力。因此,我想避免在不需要时加入该表(也就是说,如果table1或table2已经具有“ organizationID”列)

2 个答案:

答案 0 :(得分:0)

查询将执行所有联接,因为可能需要所有联接-在不同的行上。

如果您确实想限制查找次数,则可以使用case。像这样:

SELECT . . ., 
       (CASE WHEN EXISTS (SELECT 1
                          FROM table1 t1
                          WHERE t1.? = t0.? AND . . .
                         )
             THEN (SELECT ?
                   FROM table1 t1
                   WHERE t1.? = t0.? AND . . .
                  )
             WHEN EXISTS (SELECT 1
                          FROM table1 t2
                          WHERE t2.? = t0.? AND . . .
                         )
             THEN (SELECT ?
                   FROM table2 t2
                   WHERE t2.? = t0.? AND . . .
                  )
           . . .
      END)
FROM table0;

但是,这不会加快查询速度。

相反,您可能只需要适当的索引即可获得真正想要的性能。

答案 1 :(得分:0)

首先,您的IS NULL检查不完整。如果t1成功加入,t2.organization将成为NULL,并导致您多余地检查t3

先尝试一下?

SELECT
    coalesce(table1.organizationID,coalese(table2.organizationID,coalesce(table3.organizationID,0)))
FROM
          table0
LEFT JOIN table1 ON (some condition)
LEFT JOIN table2 ON (some condition) AND table1.organizationID IS NULL
LEFT JOIN table3 ON (some condition) AND table1.organizationID IS NULL AND table2.organizationID IS NULL

否则,您是否可以通过使用横向连接说服优化器短路(如果不需要,则不连接)

SELECT
  table3.organizationID
FROM
  table0
LEFT JOIN
  table1
    ON (some condition)
LEFT LATERAL JOIN
(
  SELECT table2.organizationID FROM table2 WHERE (some condition) AND table1.organizationID IS     NULL
  UNION ALL
  SELECT table1.organizationID             WHERE                      table1.organizationID IS NOT NULL
)
  table2 ON true
LEFT LATERAL JOIN
(
  SELECT table3.organizationID FROM table3 WHERE (some condition) AND table2.organizationID IS     NULL
  UNION ALL
  SELECT table2.organizationID             WHERE                      table2.organizationID IS NOT NULL
)
  table3 ON true