仅当先前的加入未找到任何内容时才离开加入
Posted
技术标签:
【中文标题】仅当先前的加入未找到任何内容时才离开加入【英文标题】:Left join only if previous join didn't find anything 【发布时间】:2019-03-28 14:33:21 【问题描述】:我尽量把它缩小。
--
假设我有三个表,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”列)
【问题讨论】:
您是只对table3
(organizationID) 中的一列感兴趣,还是对其他列感兴趣?
【参考方案1】:
查询将执行所有连接,因为可能需要所有连接——在不同的行上。
如果您真的想限制查找次数,可以使用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;
但是,这不会加快查询速度。
相反,您可能只需要适当的索引来获得您真正想要的性能。
【讨论】:
【参考方案2】:首先,您的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
【讨论】:
以上是关于仅当先前的加入未找到任何内容时才离开加入的主要内容,如果未能解决你的问题,请参考以下文章