2016-08-18 191 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

好像你在該列中一些非數值

最後,你可以通過使用計算列簡化代碼... – jarlh

+0

您正在使用哪個版本的SQLServer? – TheGameiswar

回答

7

您會認爲您的代碼可行。但是,SQL Server不保證SELECT的轉換髮生前WHERE子句篩選數據庫。在我看來這是一個錯誤。在微軟看來,這是一項優化功能。

因此,您的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確實保證條款的順序排序,所以:

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

因爲AVG()忽略NULL值,該WHERE是沒有必要的,但你可以包括,如果你喜歡。

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

然後,你可以寫代碼:

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 

所以要儘量添加避免非數字號碼與您的輸出中搞亂..

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

如果您對SQLServer的2012年,你可以嘗試使用TRY_Convert輸出爲空轉換失敗..

SELECT AVG(try_convert(DECIMAL(18,2),Reimbursement)) 
from 
table 
+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我跑了第一線,我收到並輸出像這樣。 $ 11,162 $ 11,162 $ 11,162 $ 11,162 $ 11,162 $ 10,194可能是因爲當我嘗試將其轉換爲INT時,有一個美元符號導致我的所有值? –

+0

是的美元符號和逗號分隔數以千計的數以千計也會導致它失敗,因爲它存儲爲純文本。因此,您可能必須將這些值更新爲一個數字,然後使用您的腳本。 –

相關問題