1

プロセスによって消費された秒数を 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 を数値に変換中にエラーが発生しました。

不思議なことに、条件に一致するレコードの最高値のみを取得する方法はありますか?

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。後で追加するよりも安くなります。」

于 2013-08-09T14:47:35.360 に答える