簡體   English   中英

查詢不會將 nvarchar(30) 轉換為十進制

[英]Query won't convert a nvarchar(30) to a decimal

我有以下查詢,運行時出現以下錯誤:

Conversion failed when converting the nvarchar value '247.300' to data type int.

查詢如下:

SELECT UD.SerialNumber,
       UD.ReadingDate,
       UD.ChannelName,
       CONVERT(decimal(18,2), ChannelValue) - LAG(CONVERT(decimal(18,2), ChannelValue),1,
       CONVERT(decimal(18,2), ChannelValue)) OVER (PARTITION BY ChannelName, 
       CASE ChannelValue WHEN 0 THEN 0 ELSE 1 END ORDER BY ReadingDate ASC)
FROM [Staging].[UriData] UD
WHERE UD.ChannelName IN (SELECT ChannelName FROM [Staging].[ActiveChannels])
ORDER BY ReadingDate;

這是一個小提琴: DB Fiddle

小提琴(工作正常)和這里的查詢之間的唯一區別是我必須有ChannelValueNVARCHAR因為一些數據將在文本中。 我已經過濾掉了查詢中的所有文本數據。

我還使用以下查詢對其進行了測試,但沒有顯示數據。 如果它不是一個數字,我希望它會出現在這里。

select ChannelValue
from [Staging].[UriData]
where try_convert(numeric(18, 2), ChannelValue) is null and ChannelValue is not null;

預期結果是將數字“247.300”轉換為數字並進行處理。 為什么不轉換?

如果您閱讀錯誤消息,它會抱怨int

這是來自這里的隱式演員表

CASE ChannelValue WHEN 0 THEN 0 ELSE 1 END

使用顯式轉換

 CASE CONVERT(decimal(19,3), ChannelValue) WHEN 0 THEN 0 ELSE 1 END

那么諸如247.300值將可以很好地轉換並與整數0相媲美。

盡管您還說“我已過濾掉查詢中的所有文本數據。”。 在這種情況下,您應該始終使用TRY_CONVERT ,以防操作被排序,以便在過濾器之前進行轉換。

在 SQL Server 中您不能輕易過濾掉文本值——數據庫保留重新安排操作的權利,這可能會導致錯誤。

所以,使用TRY_CONVERT()

SELECT UD.SerialNumber,
       UD.ReadingDate,
       UD.ChannelName,
       (TRY_CONVERT(decimal(18, 2), ChannelValue) -
        TRY_CONVERT(DECIMAL(18, 2), LAG(ChannelValue), 1, ChannelValue) OVER (PARTITION BY ChannelName, CASE ChannelValue WHEN '0' THEN 0 ELSE 1 END ORDER BY ReadingDate ASC))
       )
FROM [Staging].[UriData] UD
WHERE UD.ChannelName IN (SELECT ChannelName
                         FROM [Staging].[ActiveChannels]
                        )
ORDER BY ReadingDate;

如果ChannelValue是一個字符串,那么CASE的比較應該是一個字符串值。

在大多數情況下,您只需要進行一次轉換。 但是,為了避免減法出現問題,您還必須在減法之前進行轉換。

您可以使用此邏輯來簡化:

SELECT UD.SerialNumber,
       UD.ReadingDate,
       UD.ChannelName,
       (ChannelValue_d -
        LAG(ChannelValue_d), 1, ChannelValue_d) OVER (PARTITION BY ChannelName, CASE ChannelValue WHEN '0' THEN 0 ELSE 1 END ORDER BY ReadingDate ASC)
       )
FROM [Staging].[UriData] UD CROSS APPLY
     (VALUES (TRY_CONVERT(decimal(18, 2), ChannelValue) )
     ) v(ChannelValue_d)
WHERE UD.ChannelName IN (SELECT ChannelName
                         FROM [Staging].[ActiveChannels]
                        )
ORDER BY ReadingDate;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM