我有一个应该具有浮动值(价格)的数据字段,但是,数据库设计者搞砸了,现在我必须在该字段上执行聚合函数。而80%的时间数据格式正确,例如。 '80 .50',有时保存为'$ 80.50'或'$ 80.50每平方米'。
数据字段是nvarchar。我需要做的是从nvarchar中提取浮点数。我来到这里:Article on SQL Authority
然而,有些人可能会说,这可以解决我的一半问题或复合问题。该函数只返回字符串中的数字。这是'每平方米80.50美元'将返回80502.显然不会工作。我试图从=>更改正则表达式 PATINDEX('%[^ 0-9]%',@ ssAlphaNumeric)to => PATINDEX('%[^ 0-9]。[^ 0-9]%',@ ssAlphaNumeric) 不起作用。任何帮助将不胜感激。答案 0 :(得分:2)
这也应该有效,但它假设浮点数后跟一个空格,以防后面有文字。
// sample data
DECLARE @tab TABLE (strAlphaNumeric NVARCHAR(30))
INSERT @tab VALUES ('80.50'),('$80.50'),('$80.50 per sqm')
// actual query
SELECT
strAlphaNumeric AS Original,
CAST (
SUBSTRING(stralphanumeric, PATINDEX('%[0-9]%', strAlphaNumeric),
CASE WHEN PATINDEX('%[ ]%', strAlphaNumeric) = 0
THEN LEN(stralphanumeric)
ELSE
PATINDEX('%[ ]%', strAlphaNumeric) - PATINDEX('%[0-9]%', strAlphaNumeric)
END
)
AS FLOAT) AS CastToFloat
FROM @tab
从上面的示例数据中生成:
Original CastToFloat
------------------------------ ----------------------
80.50 80,5
$80.50 80,5
$80.50 per sqm 80,5
示例SQL Fiddle。
如果你想要更强大的东西,你可能要考虑编写一个CLR函数来进行正则表达式解析,而不是像这篇MSDN文章中所描述的那样:Regular Expressions Make Pattern Matching And Data Extraction Easier
答案 1 :(得分:2)
这需要您在(http://sqlfiddle.com/#!6/6ef8e/53)
上进行测试DECLARE @data varchar(max) = '$70.23 per m2'
Select LEFT(SubString(@data, PatIndex('%[0-9.-]%', @data),
len(@data) - PatIndex('%[0-9.-]%', @data) +1
),
PatIndex('%[^0-9.-]%', SubString(@data, PatIndex('%[0-9.-]%', @data),
len(@data) - PatIndex('%[0-9.-]%', @data) +1))
)
但是正如jpw已经提到过CLR上的正则表达式会更好
答案 2 :(得分:0)
受到@deterministicFail的启发,我想了一种只提取数字部分的方法(虽然它还不是100%):
DECLARE @NUMBERS TABLE (
Val VARCHAR(20)
)
INSERT INTO @NUMBERS VALUES
('$70.23 per m2'),
('$81.23'),
('181.93 per m2'),
('1211.21'),
(' There are 4 tokens'),
(' No numbers '),
(''),
(' ')
select
CASE
WHEN ISNUMERIC(RTRIM(LEFT(RIGHT(RTRIM(LTRIM(n.Val)), 1+LEN(RTRIM(LTRIM(n.Val)))-PatIndex('%[0-9.-]%', RTRIM(LTRIM(n.Val)))), LEN(RIGHT(RTRIM(LTRIM(n.Val)), 1+LEN(RTRIM(LTRIM(n.Val)))-PatIndex('%[0-9.-]%', RTRIM(LTRIM(n.Val)))))- PATINDEX('%[^0-9.-]%',RIGHT(RTRIM(LTRIM(n.Val)), 1+LEN(RTRIM(LTRIM(n.Val)))-PatIndex('%[0-9.-]%', RTRIM(LTRIM(n.Val))))))))=1 THEN
RTRIM(LEFT(RIGHT(RTRIM(LTRIM(n.Val)), 1+LEN(RTRIM(LTRIM(n.Val)))-PatIndex('%[0-9.-]%', RTRIM(LTRIM(n.Val)))), LEN(RIGHT(RTRIM(LTRIM(n.Val)), 1+LEN(RTRIM(LTRIM(n.Val)))-PatIndex('%[0-9.-]%', RTRIM(LTRIM(n.Val)))))- PATINDEX('%[^0-9.-]%',RIGHT(RTRIM(LTRIM(n.Val)), 1+LEN(RTRIM(LTRIM(n.Val)))-PatIndex('%[0-9.-]%', RTRIM(LTRIM(n.Val)))))))
ELSE '0.0'
END
FROM @NUMBERS n