试图获取所有数值和句点形式的字符串
Trying to get all numerical values and periods form string
我正在尝试使用 SELECT 语句检索数据,该语句由不同的人输入,以克为单位。由于这里似乎没有标准,因此人们编写它的一些方式:
- 200g
- 0.2KG
- 0.200kg
- 0.2
- 0.2g(e)
- 2KG
- .222
我目前在下面有这个函数 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
我正在尝试使用 SELECT 语句检索数据,该语句由不同的人输入,以克为单位。由于这里似乎没有标准,因此人们编写它的一些方式:
- 200g
- 0.2KG
- 0.200kg
- 0.2
- 0.2g(e)
- 2KG
- .222
我目前在下面有这个函数 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