代码之家  ›  专栏  ›  技术社区  ›  Tobias Schulte marmelin

如果条件为false,条件子查询是否已优化?

  •  3
  • Tobias Schulte marmelin  · 技术社区  · 16 年前

    我有一个表foo和一个表栏,其中每个foo可能有一个栏(一个栏可能属于多个foo)。

    现在,我需要选择所有带酒吧的FOO。我的SQL看起来像这样

    SELECT * 
      FROM foo f 
     WHERE [...] 
       AND ($param IS NULL OR (SELECT ((COUNT(*))>0) 
                                 FROM bar b 
                                WHERE f.bar = b.id))
    

    在运行时替换$param。

    问题是:即使参数为空,子查询也会被执行吗?或者DBMS会优化子查询吗?

    我们使用的是mysql、mssql和oracle。在上述方面,这些有什么不同吗?

    2 回复  |  直到 16 年前
        1
  •  2
  •   Thomas    16 年前

    这要看情况而定。如果每次都将该查询传递给DBMS,那么编译器应该意识到它不需要调用子查询。如果是静态过程,则取决于编译器存储执行计划的方式。如果它在第一次调用过程时存储执行计划,并且第一次调用它时$param不为空,那么它可能会在每次运行过程时实际调用子查询。

    另一方面,对于这种类型的检查,您应该考虑exists而不是count(*)。

    Select ..
    From foo f
    Where ....
        And ( $param Is Null
                Or Exists   (
                            Select 1
                            From bar b
                            Where b.id = f.bar
                            ))
    
        2
  •  1
  •   Ike Walker    16 年前

    在这种情况下,我建议您自己在应用程序代码中进行优化,而不是依靠来自3个不同RDBMS的优化器以您想要的方式一致地处理这个问题。

    如果$param为空,只需从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