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

Trying to get all numerical values and periods form string

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

我目前在下面有这个函数 returns 将所有数字字符转换为 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 保持原样。

(字母只在开头或结尾,从不在数字之间,它有时确实以 . 开头)

你可以找一些没有用到的字符,把.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

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

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