我正在尝试删除已知的alpha子串并将结果格式化为在小数点后显示两位数。
select tbl.result
, case
when CHARINDEX('searchCriteria',tbl.result) > 0 then case
when ISNUMERIC(REPLACE(tbl.result, 'searchCriteria', '')) > 0 then TRY_CONVERT(decimal(18,2),REPLACE(tbl.result, 'searchCriteria', ''))
else REPLACE(tbl.result, 'searchCriteria', '')
end
else tbl.result
end as [Substring_Removed]
from sourceTable tbl
--Msg 8114, Level 16, State 5, Line 71
--Error converting data type varchar to numeric.
的问题
我可以使用哪些策略来避免这种情况?
结果列中的典型值采用以下样式:
答案 0 :(得分:0)
This is assuming "SomeString" begins with a number and has a space after the value.
Declare @YourTable table (ID int,SomeString varchar(50))
Insert Into @YourTable values
(1,'<123 searchCriteria'),
(2,'123 searchCriteria'),
(3,'1.23'),
(4,'123,000 searchCriteria'),
(5,'1.23x10e8 searchCriteria'),
(6,'1,234.5 g/L'),
(7,'Not measured')
Select *
,TheValue = IsNull(Format(Try_Convert(float,Replace(Replace(Replace(Left(SomeString,CharIndex(' ',SomeString+' ')),',',''),'x10',''),'<','')),'#0.00'),SomeString)
From @YourTable
返回
ID SomeString TheValue
1 <123 searchCriteria 123.00
2 123 searchCriteria 123.00
3 1.23 1.23
4 123,000 searchCriteria 123000.00
5 1.23x10e8 searchCriteria 123000000.00
6 1,234.5 g/L 1234.50
7 Not measured Not measured
答案 1 :(得分:0)
使用PatExclude8K,你可以找到here,你可以这样做:
-- Sample Data
Declare @YourTable table (ID int,SomeString varchar(50))
Insert Into @YourTable values
(1,'<123 searchCriteria'),
(2,'123 searchCriteria'),
(3,'1.23'),
(4,'123,000 searchCriteria'),
(5,'1.23x10e8 searchCriteria'),
(6,'1,234.5 g/L'),
(7,'Not measured')
-- Solution:
SELECT yt.*, [Substring_Removed] =
ISNULL(CAST(CAST(NewString AS decimal(10,2)) AS varchar(12)), SomeString)
FROM @YourTable yt
CROSS APPLY dbo.PatExclude8K(SomeString, '[^0-9.]');
结果:
ID SomeString Substring_Removed
----------- ---------------------------- -----------------
1 <123 searchCriteria 123.00
2 123 searchCriteria 123.00
3 1.23 1.23
4 123,000 searchCriteria 123000.00
5 1.23x10e8 searchCriteria 1.23
6 1,234.5 g/L 1234.50
7 Not measured Not measured
为无法使用任何新功能的用户更新...
这是解决方案中的patexclude8K功能:
-- Sample Data
Declare @YourTable table (ID int,SomeString varchar(50))
Insert Into @YourTable values
(1,'<123 searchCriteria'),
(2,'123 searchCriteria'),
(3,'1.23'),
(4,'123,000 searchCriteria'),
(5,'1.23x10e8 searchCriteria'),
(6,'1,234.5 g/L'),
(7,'Not measured')
-- new solution with Patexclude8K logic baked in
SELECT yt.*, substring_removed = ISNULL(CAST(CAST(NewString AS decimal(10,2)) AS varchar(12)), yt.SomeString)
FROM @yourTable yt
CROSS APPLY
(
SELECT SUBSTRING(yt.someString, N, 1)
FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) a(x),
(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) b(x),
(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) c(x),
(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) d(x)
) iTally(N)
WHERE N <= (CONVERT(INT,LEN(yt.someString),0))
AND 0 = PATINDEX('[^0-9.]',SUBSTRING(yt.someString COLLATE Latin1_General_BIN,N,1))
FOR XML PATH('')
) patexclude(newstring);
结果相同,但此方法比我最初发布的速度快40%,因为特殊XML字符不需要特殊处理。