如何删除字母字符,然后使用SQL格式化为数字

时间:2016-12-27 18:37:32

标签: sql sql-server tsql

我正在尝试删除已知的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.

遇到Data Type Precedence

的问题

我可以使用哪些策略来避免这种情况?

结果列中的典型值采用以下样式:

  • < 123 searchCriteria
  • 123 searchCriteria
  • 1.23
  • 123,000 searchCriteria
  • 1.23x10e8 searchCriteria

2 个答案:

答案 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字符不需要特殊处理。