4

(NVARCHAR) 列の 1 つが数値範囲内にあるテーブルから行を選択しようとしています。

SELECT ID, Value
FROM Data
WHERE ISNUMERIC(Value) = 1 AND CONVERT(FLOAT, Value) < 66.6

残念ながら、SQL 仕様の一部として、AND 句を短絡する必要はありません (MSSQL Server EE 2008 では短絡する必要はありません)。詳細: SQL WHERE 句の短絡は評価されますか?

私の次の試みは、これを試して、CONVERT の遅延評価を達成できるかどうかを確認することでした。

SELECT ID, Value
FROM Data
WHERE (CASE WHEN ISNUMERIC(Value) = 1 THEN CONVERT(FLOAT, Value) < 66.6 ELSE 0 END)

しかし、CONVERT の結果に < (または任意の比較) を使用できないようです。エラーで失敗します

Incorrect syntax near '<'.

私は逃げることができます

SELECT ID, CONVERT(FLOAT, Value) AS Value
FROM Data
WHERE ISNUMERIC(Value) = 1

したがって、明らかな解決策は、選択ステートメント全体を別の SELECT と WHERE でラップし、内部選択から変換された値を返し、外部選択の場所でフィルター処理することです。残念ながら、これが私のLinq-to-sqlの問題の出番です。1つの範囲だけでなく、潜在的に多くの範囲、またはレコードの存在によってフィルタリングしています(除外した日付範囲の選択と比較がいくつかあります. )

基本的に、次のようなものを生成できるようにしたいと考えています。

SELECT ID, TypeID, Value
FROM Data
WHERE (TypeID = 4 AND ISNUMERIC(Value) AND CONVERT(Float, Value) < 66.6) 
      OR (TypeID = 8 AND ISNUMERIC(Value) AND CONVERT(Float, Value) > 99)
      OR (TypeID = 9)

(これらの where オプションのそれぞれにいくつかの他の句があります。) 内部選択で ISNUMERIC 以外の値を除外すると、これは明らかに機能しません。

前述したように、Linq-to-sql (および PredicateBulider) を使用してこれらのクエリを構築していますが、残念ながら

Datas.Where(x => ISNUMERIC(x.Value) ? Convert.ToDouble(x.Value) < 66.6 : false)

これに変換され、最初の問題が失敗します。

WHERE (ISNUMERIC([t0].[Value]) = 1) AND ((CONVERT(Float,[t0].[Value])) < @p0)

私の最後の手段は、比較ごとに同じテーブルの二重選択に対して外部結合する必要がありますが、これは実際にはアイデアの解決策ではありません。誰かが以前に同様の問題に遭遇したことがあるかどうか疑問に思っていましたか?

4

1 に答える 1

8

問題は AND 自体ではなく、NVARCHAR から FLOAT への変換だと思います

次の例を見てください。

DECLARE @Table TABLE(
        Value NVARCHAR(10)
)

INSERT INTO @Table SELECT '1'
INSERT INTO @Table SELECT '100'
INSERT INTO @Table SELECT 'A'

SELECT  *
FROM    @Table
WHERE   ISNUMERIC(Value)= 1 AND CAST(CAST(Value AS VARCHAR(10)) AS FLOAT) > 50

SELECT  *
FROM    @Table
WHERE   ISNUMERIC(Value)= 1 AND CAST(Value AS FLOAT) > 50

最後の選択は、エラーが表示される場所です

メッセージ 8114、レベル 16、状態 5、行 13 データ型 nvarchar を float に変換中にエラーが発生しました。

しかし、最初の選択はうまくいきます。

于 2010-04-01T04:31:08.727 に答える