2016-08-18 40 views
1

データベースの平均を取ろうとしています。列はAMOUNTで、NVARCHAR(300),nullとして格納されています。データ型nvarcharを数値に変換中にエラーが発生しました - SQL Server

私は数値に変換しようとすると、私は次のエラーを取得する:ここで

Msg 8114, Level 16, State 5, Line 1
Error converting datatype NVARCHAR to NUMBER

は、私が今持っているものです。

SELECT AVG(CAST(Reimbursement AS DECIMAL(18,2)) AS Amount 
FROM Database 
WHERE ISNUMERIC(Reimbursement) = 1 
    AND Reimbursement IS NOT NULL 
+0

は、あなたがその列にいくつかの数値以外の値を持っているように思える:として

alter database add Reimbursement_Value as (CASE WHEN ISNUMERIC(Reimbursement) = 1 AND Reimbursement IS NOT NULL THEN CONVERT(DECIMAL(18,2), Reimbursement)) END); 

は、その後、あなたがコードを書くことができます。

最後に、計算列を使用して、コードを簡素化することができ... – jarlh

+0

どのバージョンのSQLServerを使用していますか? – TheGameiswar

答えて

7

あなたのコードはうまくいくと思います。ただし、SELECTの変換が行われる前に、SQL ServerはWHERE句がデータベースをフィルタすることを保証しません。私の意見ではこれはバグです。 Microsoftの意見では、これは最適化機能です。

したがって、WHEREは動作するとは限りません。 CTEを使用しても、問題は解決されません。

最善の解決策は、SQL Serverの2012+で利用可能TRY_CONVERT()です:

SELECT AVG(TRY_CONVERT(DECIMAL(18,2), Reimbursement)) AS Amount 
FROM Database 
WHERE ISNUMERIC(Reimbursement) = 1 AND Reimbursement IS NOT NULL; 

以前のバージョンでは、CASEを使用することができます。 CASEそう保証条項のシーケンシャル順序、行いますAVG()WHEREは必要ありませんNULL値を、無視しますが、あなたが好きならば、あなたがそれを含めることができますので

SELECT AVG(CASE WHEN ISNUMERIC(Reimbursement) = 1 AND Reimbursement IS NOT NULL 
       THEN CONVERT(DECIMAL(18,2), Reimbursement)) 
      END) 
FROM Database; 

を。

select avg(Reimbursement_Value) 
from database 
where Reimbursement_Value is not null; 
1

Quote from MSDN ...

ISNUMERIC returns 1 for some characters that are not numbers, such as plus (+), minus (-), and valid currency symbols such as the dollar sign ($). For a complete list of currency symbols, see money and smallmoney

select isnumeric('+')---1 
select isnumeric('$')---1 

ので、あなたのouputをいじり数値以外の数字を避けるために追加しよう..

WHERE Reimbursement NOT LIKE '%[^0-9]%' 

あなたがのSQLServer 2012上にある場合は、 TRY_Convertを使って変換失敗のためにnullを出力しようとするとよいでしょう。

+1

'try_convert()'が正しい答えです。 –

0

Nvarcharでは、 '$'、 '。'、または(、)で値を見つけようとしています。私はこのliktクエリを実行します:

SELECT Amount 
FROM database 
WHERE Amount LIKE '%$%' OR 
     Amount LIKE '%.%' OR 
     Amount LIKE '%,%' 

はあなたが取得し、私の推測では、あなたには、いくつかの行が返さ取得し、それらの行を更新して、もう一度それをしようとするものを参照してください。

現在のところ、クエリではすべて数値ではないすべての数値が取得されるため、失敗する理由もあります。代わりにこれを実行してみてください:

SELECT AVG(CAST(Reimbursement AS DECIMAL(18,2)) AS Amount 
FROM Database 
--Changed ISNUMERIC() = to 0 for true so it will only pull numeric numbers. 
WHERE ISNUMERIC(Reimbursement) = 0 and Reimbursement IS NOT NULL 
+0

こんにちは@Wes Palmer私は最初の行を実行し、私はこれを受信し、出力します。私はINTにそれをCONVERしようとすると、$ 11162 $ 11162 $ 11162 $ 11162 $ 11162 $ 10194は、それはすべて私の値をリードするドル記号があるという事実によるものだろうか? –

+0

はい数千から数千を切り離すためのドル記号とカンマも、プレーンテキストとして格納されているため、失敗します。したがって、これらの値を数だけ更新してからスクリプトを使用する必要があります。 –

関連する問題