我有一个字段可以将进程消耗的秒数存储为varchar。我正在进行一个简单的查询,以便在SQL服务器中使用以下查询找到花费时间最长的行。
select top 1 Cusip from Cusipprocesstime
where
status != 'In Progress' and status is not null
order by cast(status as decimal(18,7)) desc
此状态设置为进程消耗的秒数。在进行中,状态设置为“进行中”。
当我运行上述查询时,如果没有“正在进行”状态的记录,则查询正常。
如果存在状态为“进行中”的记录,则查询失败,指出“将数据类型varchar转换为数字时出错。
想知道,有没有办法我们只能为符合条件的记录检索最高值。
答案 0 :(得分:5)
您需要在转换前检查数值:
select top 1 Cusip
from Cusipprocesstime
where status != 'In Progress' and status is not null
order by (case when isnumeric(status) = 1 then cast(status as decimal(18,7)) end) desc;
SQL Server重新排列操作顺序。换句话说,它决定在从表中读取数据时进行转换 - 这是在where
子句生效之前。 case
语句是唯一保证评估顺序的语句(即使是子查询和CTE也不一定适用于此)。这就是为什么这个版本有效。
编辑:
ANSI标准指定了处理的逻辑顺序,我相信SQL Server与此一致(参见here)。但文档非常明确:
请注意,确定语句的实际物理执行 由查询处理器和订单可能会有所不同。
特别是(尽管没有详细记录),SQL Server在将表读入系统时添加了新变量。这是有道理的,因为数据已经从物理格式转换为内存中使用的格式,因此添加新变量会产生很少的开销。在这种情况下,查询“思考”类似于:“天哪,我需要将该值转换为decimal
以便稍后在order by
子句中。让我现在就做,并且只是通过处理传递值。这比以后尝试添加它要便宜。“