我有以下查询,该查询在运行时会出现以下错误:
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
小提琴(工作正常)与此处的查询之间的唯一区别是,我必须拥有ChannelValue
列NVARCHAR
,因为某些数据将以文本形式出现。我已经过滤掉了查询中的所有文本数据。
我还通过以下查询对其进行了测试,但数据未显示。如果不是数字,我希望它会出现在这里。
select ChannelValue
from [Staging].[UriData]
where try_convert(numeric(18, 2), ChannelValue) is null and ChannelValue is not null;
预期结果是将数字“ 247.300”转换为数字并进行处理。为什么不转换?
答案 0 :(得分:2)
如果您阅读错误消息,则会抱怨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
,以防操作被排序,从而使转换发生在过滤器之前。
答案 1 :(得分:0)
您不能轻易地在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;