我想知道 SELECT
中的表达式是否可行要评估与 WHERE
不匹配的行的语句列表条款?
来自执行顺序documented here ,似乎SELECT
在WHERE
之后很长时间进行评估,但是我在现实生活中的查询中遇到了一个非常奇怪的问题类似于下面的查询。
为了让您了解上下文,在示例中,SomeOtherTable
有一个a_varchar
始终包含 code
数值的列105,但可能包含其他代码的非数字值。
查询语句有效:
SELECT an_id, an_integer FROM SomeTable
UNION ALL
SELECT an_id, CAST(a_varchar AS int)
FROM SomeOtherTable
WHERE code = 105
以下查询提示无法转换 a_varchar
至int
:
SELECT 1
FROM (
SELECT an_id, an_integer FROM SomeTable
UNION ALL
SELECT an_id, CAST(a_varchar AS int)
FROM SomeOtherTable
WHERE code = 105
) i
INNER JOIN AnotherOne a
ON a.an_id = i.an_id
最后,以下查询有效:
SELECT 1
FROM (
SELECT an_id, an_integer FROM SomeTable
UNION ALL
SELECT
an_id,
CASE code WHEN 105 THEN CAST(a_varchar AS int) ELSE NULL END
FROM SomeOtherTable
WHERE code = 105
) i
INNER JOIN AnotherOne a
ON a.an_id = i.an_id
因此,我能找到的唯一解释是 JOIN
,查询以不同的方式得到优化 CAST(a_varchar AS int)
即使 code <> 105
也会被执行.
查询针对 SQL SERVER 2008 运行。
最佳答案
当然。
您引用的文档中有一个名为SELECT 语句的逻辑处理顺序的部分。这不是物理处理顺序。它解释了查询本身是如何解释的。例如,select
子句中定义的别名不能在 where
子句中引用,因为 where
子句逻辑上 首先处理。
事实上,SQL Server有能力在读取数据时通过进行各种数据转换操作来优化查询。这是一个很好的性能优势,因为数据位于本地内存中,并且操作可以简单地就地完成。但是,以下操作可能会失败并出现运行时错误:
select cast(a_varchar as int)
from table t
where a_varchar not like '%[^0-9]%';
在实际处理流程中尝试转换之后应用过滤器。我碰巧认为这是一个错误;想必,微软的人并不这么认为,因为他们没有费心去解决这个问题。
有两种解决方法可用。第一个是 try_convert()
,它执行转换并在失败时返回 NULL
,而不是运行时错误。第二个是 case
语句:
select (case when a_varchar not like '%[^0-9]%' then cast(a_varchar as int) end)
from table t
where a_varchar not like '%[^0-9]%';
关于sql - 有时可以对不匹配 WHERE 子句的行计算 SELECT 表达式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26180070/