我有一个表格foo和一个表格栏,其中每个foo可能有一个条形图(并且一个条形图可能属于多个foos)。
现在我需要用酒吧选择所有的泡沫。我的sql看起来像这样
SELECT *
FROM foo f
WHERE [...]
AND ($param IS NULL OR (SELECT ((COUNT(*))>0)
FROM bar b
WHERE f.bar = b.id))
在运行时替换$ param。
问题是:即使param为null,子查询是否会被执行,或者dbms会优化子查询吗?
我们正在使用mysql,mssql和oracle。这些与上述有什么区别?
答案 0 :(得分:2)
这取决于。如果每次都将该查询传递给DBMS,那么编译器应该意识到它不需要调用子查询。如果它是静态过程,那么它取决于编译器如何存储执行计划。如果它在第一次调用过程时存储执行计划,并且第一次调用它时$ param不为null,那么它可能实际上在每次运行过程时调用子查询。
另一方面,对于此类检查,您应该考虑存在而不是计数(*)
Select ..
From foo f
Where ....
And ( $param Is Null
Or Exists (
Select 1
From bar b
Where b.id = f.bar
))
答案 1 :(得分:1)
在这种情况下,我建议您自己在应用程序代码中进行优化,而不是依赖来自3个不同RDBMS的优化器来始终如一地处理它。
如果$ param为null,只需从foo表中选择。 如果没有,请加入吧台。
伪码:
if ($param is null)
SELECT *
FROM foo f
WHERE [...]
else
SELECT distinct f.*
FROM foo f
inner join bar b on f.bar = b.id
WHERE [...]
end if