【问题标题】:T-SQL to pull decimal values from a stringT-SQL 从字符串中提取十进制值
【发布时间】:2015-04-10 14:21:21
【问题描述】:

好的,我想做的是从字符串中提取十进制值。我的问题是字符串不统一。有些可能是 6.9% 或 5.2mg/L,有些可能根本没有数值。我想做的是只返回字符串中的小数(或整数)值,如果不存在则返回 NULL。

这个功能我试过了:

CREATE FUNCTION dbo.udf_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

但这只会返回没有小数位的数字。

【问题讨论】:

  • 可能有负值吗?
  • @HABO 不,不会有负值

标签: sql tsql


【解决方案1】:

另一种方法是删除字符串之后和字符串之前的字符。以下表达式执行此操作:

select val, 
       stuff(stuff(val+'x', patindex('%[0-9][^0-9.]%', val+'x') + 1, len(val), ''
                  ), 1, patindex('%[0-9]%', val) - 1, '')
from (values ('test123 xxx'), ('123.4'), ('123.4yyyyy'), ('tasdf 8.9'), ('asdb'), ('.2345')) as t(val);

stuff()去掉数字后面的字符。 +'x' 处理数字在字符串末尾时出现的问题。第一部分处理数字之前的部分。

这确实假设字符串中只有一个数字。您可以使用 where 子句检查这一点:

where val not like '%[0-9]%[^0-9.]%[0-9]%'

【讨论】:

  • 这很好用而且非常简洁。我希望我可以将这三个都标记为答案。
【解决方案2】:

您只需要在两个PATINDEX 表达式中添加一个.(点):

CREATE FUNCTION dbo.Udf_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

【讨论】:

    【解决方案3】:

    使用这个函数它也会返回十进制数

        CREATE Function udf_ExtractNumber (@String varchar(256))
    RETURNS VARCHAR(256)
    AS
    BEGIN
    DECLARE @AlphaNumeric varchar(256)
    ,@Res varchar(256)
    
    SET @AlphaNumeric = @String
    SET @Res = NULL
    
    WHILE (PATINDEX('%[0-9]%', @AlphaNumeric) > 0 )
    BEGIN
        IF (PATINDEX('%[0-9]%', @AlphaNumeric) >0 AND PATINDEX('%[0-9]%', @AlphaNumeric) < CHARINDEX('.', @AlphaNumeric))
                    BEGIN 
                        SET @Res = CONCAT(@Res ,SUBSTRING(@AlphaNumeric, PATINDEX('%[0-9]%', @AlphaNumeric), 1) )
                        SET @AlphaNumeric = RIGHT(@AlphaNumeric,len(@AlphaNumeric)- PATINDEX('%[0-9]%', @AlphaNumeric))
                    END
                ELSE IF (CHARINDEX('.', @AlphaNumeric) >0  AND CHARINDEX('.', @AlphaNumeric) < PATINDEX('%[0-9]%', @AlphaNumeric))
                    BEGIN 
                        SET @Res = CONCAT(@Res ,SUBSTRING(@AlphaNumeric, CHARINDEX('.', @AlphaNumeric), 1) )
                        SET @AlphaNumeric = RIGHT(@AlphaNumeric,len(@AlphaNumeric)- CHARINDEX('.', @AlphaNumeric))
                    END
                ELSE IF (PATINDEX('%[0-9]%', @AlphaNumeric) >0)
                    BEGIN 
                        SET @Res = CONCAT(@Res, SUBSTRING(@AlphaNumeric, PATINDEX('%[0-9]%', @AlphaNumeric), 1) )
                        SET @AlphaNumeric = RIGHT(@AlphaNumeric,len(@AlphaNumeric)- PATINDEX('%[0-9]%', @AlphaNumeric))
                    END
                ELSE IF (CHARINDEX('.', @AlphaNumeric) >0 )
                    BEGIN 
                        SET @Res = CONCAT(@Res,SUBSTRING(@AlphaNumeric, CHARINDEX('.', @AlphaNumeric), 1))
                        SET @AlphaNumeric = RIGHT(@AlphaNumeric,len(@AlphaNumeric)- CHARINDEX('.', @AlphaNumeric))
        END
    
    END
    Return @Res
    END
    

    选择 dbo.udf_ExtractNumber ('AD645.23DGD')

    【讨论】:

      【解决方案4】:

      我认为我有最有效的方法,因为它不需要循环,而且最简单,因为我在一条短线中完成了所有字符串操作。看看吧:

      SELECT  string,
              CASE
                  --If there's a number, then return it
                  WHEN PATINDEX('%[0-9]%',string) != 0 
                      --Pretty much find the first number and last number, then return that section(It's off by one so I so I add 1 at the end)
                      THEN SUBSTRING(string,PATINDEX('%[0-9]%',string),DATALENGTH(string) - PATINDEX('%[0-9]%',REVERSE(string)) + 1)
                  --If there are no numbers, return NULL
                  ELSE NULL
              END return_int
      FROM
      (
          SELECT '123456789.3243421341% of mg/L blah blah blah whitespace    ' AS string
          UNION ALL
          SELECT 'No numbers here'
      ) A
      

      结果:

      string                                                      return_int
      ----------------------------------------------------------- -----------------------------------------------------------
      123456789.3243421341% of mg/L blah blah blah whitespace     123456789.3243421341
      No numbers here                                             NULL
      

      【讨论】:

        猜你喜欢
        • 2013-06-21
        • 1970-01-01
        • 2021-12-01
        • 1970-01-01
        • 2017-04-25
        • 1970-01-01
        • 1970-01-01
        • 2022-01-25
        相关资源
        最近更新 更多