试图获取所有数值和句点形式的字符串

时间:2018-11-15 13:45:11

标签: sql-server string tsql sql-server-2005

我正在尝试使用SELECT语句检索的数据,该语句由各种人输入,以克为单位。因为似乎没有标准,所以这里是人们编写它的一些方式:

  • 200克
  • 0.2公斤
  • 0.200千克
  • 0.2
  • 0.2g(e)
  • 2公斤
  • .222

我目前在下面有此函数,该函数将所有数字字符返回到NVARCHAR中,然后我可以将其转换为十进制以用于计算。

ALTER FUNCTION [dbo].[fn_GetNumeric]
(@strAlphaNumeric VARCHAR(256))
RETURNS VARCHAR(256)
AS
BEGIN
DECLARE @intAlpha INT
SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric)
BEGIN
WHILE @intAlpha > 0
BEGIN
SET @strAlphaNumeric = STUFF(@strAlphaNumeric, @intAlpha, 1, '' )
SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric )
END
END
RETURN ISNULL(@strAlphaNumeric,0)
END

在某些情况下,此方法确实可以正常工作,但是例如,任何写为“ 0.2 ...”的数据都将变成“ 2”,这在处理克和千克时无济于事。

我需要它输出到DECIMAL或NVARCHAR并保留小数位,以便0.2保持0.2不变,而0.200保持如此。

(字母只出现在数字的开头或结尾,永远不会以数字.开头)

2 个答案:

答案 0 :(得分:0)

您可以找到一些未使用的字符,并用它替换.0。然后放回去:

 BEGIN

DECLARE @intAlpha INT

    SET @strAlphaNumeric = REPLACE(@strAlphaNumeric, '.0', '#');
    SET @strAlphaNumeric = REPLACE(@strAlphaNumeric, '0.', '##');
    SET @strAlphaNumeric = REPLACE(@strAlphaNumeric, '.', '###');

    SET @intAlpha = PATINDEX('%[^0-9#]%', @strAlphaNumeric)

    WHILE @intAlpha > 0
    BEGIN
        SET @strAlphaNumeric = STUFF(@strAlphaNumeric, @intAlpha, 1, '' )
        SET @intAlpha = PATINDEX('%[^0-9#]%', @strAlphaNumeric )
    END

    SET @strAlphaNumeric = REPLACE(@strAlphaNumeric, '###', '.')
    SET @strAlphaNumeric = REPLACE(@strAlphaNumeric, '##', '0.');
    SET @strAlphaNumeric = REPLACE(@strAlphaNumeric, '#', '.0');

SELECT ISNULL(@strAlphaNumeric,0)
END

或仅添加.

PATINDEX('%[^0-9.]%', @strAlphaNumeric)

但是如果您使用类似te....st 5.0 kg这样的字符串,则会遇到问题,因此最好将.0替换为特殊内容。

请注意,在示例中,我用#替换,但是您可以用其中五个替换,以使值更独特-例如,#####

答案 1 :(得分:0)

在T-SQL中进行字符串解析始终是一个挑战。但是在这种情况下,SUBSTRING可能会更容易。

您提到了这一点:字母永远只出现在数字的开头或结尾,

所以基本上,我们只需要找到数字在字符串中的开始和结束位置。

看看这个:

DECLARE @String NVARCHAR(100)

SET @String = 'This is k.g. or g it''s .0456 not g'

SELECT PATINDEX('%[0-9 ].%[0-9]%', @String ) --Where is the first occurance of a number
SELECT PATINDEX('%[0-9]%', REVERSE(@String)) --Flip the string and tell me from the other end where that number occurs
SELECT LEN(@String) - PATINDEX('%[0-9 ].%[0-9]%', REVERSE(@String)) - PATINDEX('%[0-9]%', @String ) +2 --substract those from the length and add 2, tells me how long it is.

--The above is basically where the number starts and it's length in the string.
--Then use substring to pull it all out.
SELECT SUBSTRING(@String, PATINDEX('%[0-9 ].%[0-9]%', @String ), LEN(@String) - PATINDEX('%[0-9]%', REVERSE(@String)) - PATINDEX('%[0-9 ].%[0-9]%', @String ) +2)

--larger sample set
IF OBJECT_ID('tempdb..#TestData') IS NOT NULL
DROP TABLE #TestData

CREATE TABLE #TestData (
NumberData NVARCHAR(100)
)

INSERT INTO #TestData (
                          [NumberData]
                      )
VALUES
('200g')
,('0.2KG')
,('0.200kg')
,('0.2')
,('0.2g(e)')
,('0.2000000k.g.')
,('grams 0.345')
,('This is k.g. 0.456 not g')
,('.456kg')

SELECT *, SUBSTRING([NumberData], PATINDEX('%[0-9 ].%[0-9]%', [NumberData] ), LEN([NumberData]) - PATINDEX('%[0-9]%', REVERSE([NumberData])) - PATINDEX('%[0-9 ].%[0-9]%', [NumberData] ) +2)FROM #TestData