Sql - WHERE 条件的显式顺序?

Posted

技术标签:

【中文标题】Sql - WHERE 条件的显式顺序?【英文标题】:Sql - Explicit order of WHERE conditions? 【发布时间】:2016-03-07 16:12:58 【问题描述】:

有没有办法明确说明 WHERE 条件发生的顺序?我意识到查询优化器将查看 WHERE 子句的所有部分以确定满足查询的最有效方法,如这些答案中所述:

Does order of where clauses matter in SQL

SQL - Does the order of WHERE conditions matter?

但是,有没有办法检查其他条件将依赖的条件?这些线程中的一个答案涉及我所追求的,但没有提供解决方案:

select *
from INFORMATION_SCHEMA.TABLES
where ISNUMERIC(table_name) = 1 and CAST(table_name as int) <> 0

这可能会失败,因为可以在确定 table_name 字段是否为数字之前评估 CAST(因此会抛出无效转换错误)。

肯定有办法做到这一点吗?

【问题讨论】:

【参考方案1】:

使用派生表:

SELECT *
FROM (
      SELECT *
      FROM INFORMATION_SCHEMA.TABLES
      WHERE ISNUMERIC(table_name)=1
     ) AS i
WHERE CAST(table_name AS INT)<>0

或者,很可能按顺序运行,您可以使用 CASE 语句:

SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE 0<>(CASE WHEN ISNUMERIC(table_name)=1 
          THEN CAST(table_name AS INT)
          ELSE 0 END)

应该注意的是,对于 SQL Server,存在 CASE 技巧会失败的情况。见documentation on CASE, Remarks:

CASE 语句按顺序评估其条件,并在满足条件的第一个条件处停止。 在某些情况下,在 CASE 语句接收表达式的结果作为其输入之前计算表达式。评估这些表达式时可能会出错。首先评估出现在 CASE 语句的 WHEN 参数中的聚合表达式,然后将其提供给 CASE 语句。例如,以下查询在生成 MAX 聚合的值时会产生除以零错误。这发生在评估 CASE 表达式之前。

WITH Data (value) AS 
( 
SELECT 0 
UNION ALL 
SELECT 1 
) 
SELECT 
   CASE 
      WHEN MIN(value) <= 0 THEN 0 
      WHEN MAX(1/value) >= 100 THEN 1 
   END 
FROM Data ;

我怀疑其他 RDBMS 实现也可能如此。

【讨论】:

不漂亮,但我会接受。谢谢!【参考方案2】:

我认为您是在问评估是否会短路 - 阅读此内容可能会有所帮助:

Is the SQL WHERE clause short-circuit evaluated?

因此,您可能需要在尝试第二个条件之前评估第一个条件。在 MSSQL 中,您可以使用 CTE 来执行第一个操作。或者,另一种选择可能是使用 CASE 仅在某些条件下执行第二个。

【讨论】:

以上是关于Sql - WHERE 条件的显式顺序?的主要内容,如果未能解决你的问题,请参考以下文章

按添加的 WHERE 条件的顺序对 SQL 输出进行排序

SQL where 条件顺序对性能的影响有哪些

sql里 where和order by一起使用是怎样的顺序

Oracle数据库Where条件执行顺序

sql where条件中入参判断

性能优化实战-join与where条件执行顺序