1

我有一个字段将进程消耗的秒数存储为 varchar。我正在做一个简单的查询,以使用 SQL Server 中的以下查询查找花费时间最长的行。

 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 转换为数字时出错。

想知道,有没有一种方法可以仅检索与条件匹配的记录的最高值。

4

1 回答 1

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 与此一致(参见此处)。但是,文档非常明确:

请注意,语句的实际物理执行由查询处理器确定,并且顺序可能与此列表不同。

特别是(虽然没有很好地记录),SQL Server 在将表读入系统时会添加新变量。这是有道理的,因为数据已经从物理格式转换为内存中使用的格式,因此添加新变量几乎不会产生开销。在这种情况下,查询正在“思考”类似:“天哪,我需要decimal稍后在order by子句中将该值转换为 for。让我现在就做,然后将值传递给处理。那将比以后尝试添加它便宜。”

于 2013-08-09T14:47:35.360 回答