如何将SQL子字符串转换为十进制?
我有一个varchar列,表PriceTerm中有各种字符串。所以我想把其中一些复制到另一个专栏 因此,源名称和格式是如何将SQL子字符串转换为十进制?,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我有一个varchar列,表PriceTerm中有各种字符串。所以我想把其中一些复制到另一个专栏 因此,源名称和格式是 [AdditionalDescription] [varchar](255) NOT NULL 和目的地 [PercentAddition] [decimal](28, 10) NOT NULL 我只想强制转换那些包含由SQL拾取的% select AdditionalDescription from PriceTerm where AdditionalDescriptio
[AdditionalDescription] [varchar](255) NOT NULL
和目的地
[PercentAddition] [decimal](28, 10) NOT NULL
我只想强制转换那些包含由SQL拾取的%
select AdditionalDescription from PriceTerm where AdditionalDescription like '%[%]%'
输出是这样的
AdditionalDescription
7,5 %
7,5%
7,5%
6 %
7,5%
6 %
3 %
....
返回1696475行,因此数量很多
显然,我必须先删除%符号,然后才能将其转换为十进制值
所以我认为这是几个子步骤
SELECT
CONVERT(decimal(28,10), LTRIM(RTRIM(REPLACE(REPLACE([ADDITIONALDESCRIPTION], ',', '.'), '%', ''))))
FROM PriceTerm
WHERE AdditionalDescription like '%[%]%'
SELECT
CAST(LTRIM(RTrim(REPLACE(REPLACE([ADDITIONALDESCRIPTION], ',', '.'), '%', ''))) AS Decimal(28,10))
FROM PriceTerm
WHERE AdditionalDescription like '%[%]%'
两者都返回了相同的错误
将数据类型varchar转换为数字时出错
但是下面的工作
挑选
转换(十进制(28,10)、LTRIM(RTRIM(替换(替换('5,8%,',',','),'%,''),'%,''))
从价格术语
其中,类似“%[%]”的附加说明
我试着列出那些满足条件但转换失败的
挑选
LTRIM(RTRIM(替换(替换([附加说明],,,,,,,,,,,),,,,,))作为百分比添加
从价格术语
其中(类似“%[%]%”的附加描述)和ISNUMERIC(LTRIM(RTRIM(替换(替换([AdditionalDescription],“,”,“,”),“%,”))=0
奇怪,这些都不包含%char
更新2:
我尝试过滤掉无法使用此SQL转换的数据
SELECT AdditionalDescription
FROM PriceTerm
WHERE Created BETWEEN '2004' AND '2005' AND
AdditionalDescription like '%[%]%' AND
PercentAddition = 0 AND
ISNUMERIC(RTRIM(LTRIM(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.')))) = 0
输出:
AdditionalDescription
Snabbleverans + 30 %
Snabbleverans + 30 %
455 € + 4%
1,5 % (minimi 4,20 €)
1,5 % (minimi 4,20 €)
bränsle 7,5% ingår.
因此,这些字符串包含%,但无法将其转换为小数。我想跳过那些
计算有效数字
SELECT Count(*)
FROM PriceTerm
WHERE Created BETWEEN '2004' AND '2005' AND
AdditionalDescription like '%[%]%' AND
PercentAddition = 0 AND
ISNUMERIC(RTRIM(LTRIM(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.')))) = 1
80051
更新百分比添加列
UPDATE PriceTerm
SET PercentAddition = CONVERT(decimal(28,10), RTRIM(LTRIM(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.'))))
WHERE Created BETWEEN '2004' AND '2005' AND
AdditionalDescription LIKE '%[%]%' AND
PercentAddition = 0
AND ISNUMERIC(RTRIM(LTRIM(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.')))) = 1
结果
将数据类型varchar转换为数字时出错
有人知道原因吗
更新3:
例如,上面所有无法解析的奇怪行都将被跳过
+ 30 (1.30*42.4sek=55.12sek)
7.5*
7.5*
7..5
以上全部转换为0。只有那些将转换为十进制:
7,5% -> 7.5
7,7 % -> 7.7
2.5 -> 2.5
我还试图弄清楚SQL CASE WHEN是如何工作的。有什么有用的吗?
我试过这个:
UPDATE PriceTerm
SET PercentAddition =
CASE
WHEN ISNUMERIC(RTRIM(LTRIM(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.')))) = 1 THEN
CONVERT(decimal(28,10), RTRIM(LTRIM(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.'))))
ELSE
0.0
END
WHERE Created BETWEEN '2004' AND '2005' AND
AdditionalDescription LIKE '%[%]%' AND
PercentAddition = 0
AND ISNUMERIC(RTRIM(LTRIM(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.')))) = 1
将数据类型varchar转换为数字时输出仍然错误。
我甚至考虑过一个存储过程,但我以前从未使用过。
SQL Server 2012已尝试转换,这在本例中非常有用。但我没有找到类似的2008 R2替代方案。不知道这将有多高效:
Select convert(decimal(28,10), rtrim(ltrim(replace(REPLACE(AdditionalDescription,'%',''), ',','.')))) As AdditionalDescription
from PriceTerm
where AdditionalDescription like '%[%]%'
说明:
,
替换为
Select
convert(decimal(28,10),replace(replace(replace(rtrim(ltrim(AdditionalDescription)), ' ',''),',','.'),'%','')) AS PercentAddition
from test
where replace(rtrim(ltrim(AdditionalDescription)), ' ','')
like '[0-9]%[,.]%[%0-9]'
and
isnumeric(replace(replace(replace(rtrim(ltrim(AdditionalDescription)), ' ',''),',','.'),'%',''))=1
解释'[0-9]%[,.]%[%0-9]'
:
-我们只对数据以数字开头的情况感兴趣[0-9]
-数字后可能包含任何字符。我们在%
子句中处理带有where
的非数字isnumeric
-我们有[,.]
或,
的数据
-在%
之后,它可以包含任何字符。我们在[,.]
子句中处理带有where
的非数字isnumeric
-我们希望数据以数字或[%0-9]
结尾%
'[0-9]%[,.]%[%0-9]'
参考文献:
像
-不要担心这会有多高效:
Select convert(decimal(28,10), rtrim(ltrim(replace(REPLACE(AdditionalDescription,'%',''), ',','.')))) As AdditionalDescription
from PriceTerm
where AdditionalDescription like '%[%]%'
说明:
,
替换为
Select
convert(decimal(28,10),replace(replace(replace(rtrim(ltrim(AdditionalDescription)), ' ',''),',','.'),'%','')) AS PercentAddition
from test
where replace(rtrim(ltrim(AdditionalDescription)), ' ','')
like '[0-9]%[,.]%[%0-9]'
and
isnumeric(replace(replace(replace(rtrim(ltrim(AdditionalDescription)), ' ',''),',','.'),'%',''))=1
解释'[0-9]%[,.]%[%0-9]'
:
-我们只对数据以数字开头的情况感兴趣[0-9]
-数字后可能包含任何字符。我们在%
子句中处理带有where
的非数字isnumeric
-我们有[,.]
或,
的数据
-在%
之后,它可以包含任何字符。我们在[,.]
子句中处理带有where
的非数字isnumeric
-我们希望数据以数字或[%0-9]
结尾%
'[0-9]%[,.]%[%0-9]'
参考文献:
像
-这不是最快的方法,但请尝试以下方法:
SELECT CONVERT(DECIMAL(5, 2), REPLACE(REPLACE(AdditionalDescription, '%', ''), ',', '.')) AS DecimalValue
FROM PriceTerm
WHERE AdditionalDescription LIKE '%[%]%'
这将用空字符串替换%,用点替换逗号,因此7,5%看起来像7.5,然后转换为十进制。这不是最快的方法,但请尝试以下方法:
SELECT CONVERT(DECIMAL(5, 2), REPLACE(REPLACE(AdditionalDescription, '%', ''), ',', '.')) AS DecimalValue
FROM PriceTerm
WHERE AdditionalDescription LIKE '%[%]%'
这将用空字符串替换%,用点替换逗号,因此7,5%看起来像7.5,然后转换为十进制。事实证明,最难的部分是验证字符串是否为数字。内置过程IsNumeric返回假阳性。即使结果为1,转换也无法将字符串转换为十进制。拯救行动是伴随着谷歌而来的 我使用存储过程
CREATE FUNCTION dbo.isReallyNumeric
(
@num VARCHAR(64)
)
RETURNS BIT
BEGIN
IF LEFT(@num, 1) = '-'
SET @num = SUBSTRING(@num, 2, LEN(@num))
DECLARE @pos TINYINT
SET @pos = 1 + LEN(@num) - CHARINDEX('.', REVERSE(@num))
RETURN CASE
WHEN PATINDEX('%[^0-9.-]%', @num) = 0
AND @num NOT IN ('.', '-', '+', '^')
AND LEN(@num)>0
AND @num NOT LIKE '%-%'
AND
(
((@pos = LEN(@num)+1)
OR @pos = CHARINDEX('.', @num))
)
THEN
1
ELSE
0
END
END
GO
然后像这样使用它:
UPDATE PriceTerm
SET PercentAddition = CONVERT(decimal(28,10), RTRIM(LTRIM(REPLACE(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.'), '&', ''))))
WHERE AdditionalDescription LIKE '%[%]%' AND
dbo.isreallynumeric(RTRIM(LTRIM(REPLACE(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.'), '&', '')))) = 1 AND
PercentAddition = 0
事实证明,最难的部分是验证字符串是否为数字。内置过程IsNumeric返回假阳性。即使结果为1,转换也无法将字符串转换为十进制。拯救行动是伴随着谷歌而来的 我使用存储过程
CREATE FUNCTION dbo.isReallyNumeric
(
@num VARCHAR(64)
)
RETURNS BIT
BEGIN
IF LEFT(@num, 1) = '-'
SET @num = SUBSTRING(@num, 2, LEN(@num))
DECLARE @pos TINYINT
SET @pos = 1 + LEN(@num) - CHARINDEX('.', REVERSE(@num))
RETURN CASE
WHEN PATINDEX('%[^0-9.-]%', @num) = 0
AND @num NOT IN ('.', '-', '+', '^')
AND LEN(@num)>0
AND @num NOT LIKE '%-%'
AND
(
((@pos = LEN(@num)+1)
OR @pos = CHARINDEX('.', @num))
)
THEN
1
ELSE
0
END
END
GO
然后像这样使用它:
UPDATE PriceTerm
SET PercentAddition = CONVERT(decimal(28,10), RTRIM(LTRIM(REPLACE(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.'), '&', ''))))
WHERE AdditionalDescription LIKE '%[%]%' AND
dbo.isreallynumeric(RTRIM(LTRIM(REPLACE(REPLACE(REPLACE(AdditionalDescription,'%',''), ',','.'), '&', '')))) = 1 AND
PercentAddition = 0
看起来你没有干净的数据。列中只填充了各种非数字字符。也许你必须清理数据。是的,我同意。但是我怎么能做到呢?我必须过滤