仅从匹配条件的记录中检索顶行

时间:2013-08-09 14:44:46

标签: sql sql-server

我有一个字段可以将进程消耗的秒数存储为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转换为数字时出错。

想知道,有没有办法我们只能为符合条件的记录检索最高值。

1 个答案:

答案 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子句中。让我现在就做,并且只是通过处理传递值。这比以后尝试添加它要便宜。“