【问题标题】:Extract numbers from a text in SQL Server从 SQL Server 中的文本中提取数字
【发布时间】:2012-03-09 06:31:45
【问题描述】:

我正在搜索脚本以从 sql server 中的文本中提取数字,我发现了这个

CREATE FUNCTION [dbo].[GetNumbersFromText](@String VARCHAR(2000))
RETURNS @Number TABLE (Number INT)
AS
BEGIN
DECLARE @Count INT
DECLARE @IntNumbers VARCHAR(1000)
SET @Count = 0
SET @IntNumbers = ''
WHILE @Count <= LEN(@String)
BEGIN
--Find a numeric charactor
IF SUBSTRING(@String,@Count,1) >= '0' AND SUBSTRING(@String,@Count,1) <= '9'
BEGIN
SET @IntNumbers = @IntNumbers + SUBSTRING(@String,@Count,1)
END
--If the next charactor is not a numeric one, the current number ends, so add a    separator
IF (SUBSTRING(@String,@Count+1,1) < '0'OR SUBSTRING(@String,@Count+1,1) > '9') AND    SUBSTRING(@String,@Count,1) >= '0' AND SUBSTRING(@String,@Count,1) <= '9'
BEGIN
SET @IntNumbers = @IntNumbers + ','
END
SET @Count = @Count + 1
END
---Split string to give a table with the numbers in the text
INSERT INTO @Number
SELECT DISTINCT items FROM dbo.Split(@IntNumbers, ',')
return
END

然后这样称呼它

SELECT Number FROM Dbo.[GetNumbersFromText]('Give me 120 this week and 50 next week')

它工作正常,但我需要更短的代码。我可以使用 patindex 从文本中提取数字吗? 请任何人分享这样做的小而好的逻辑。谢谢

【问题讨论】:

  • 为什么需要“更短的代码”和“小逻辑”?如果您的功能正常工作并且表现可以接受,那么根本没有理由更改它。

标签: sql sql-server tsql


【解决方案1】:

这有点短。将其变成使用递归 CTE 查找数字的内联表函数。

create function [dbo].[GetNumbersFromText](@String varchar(2000))
returns table as return
(
  with C as
  (
    select cast(substring(S.Value, S1.Pos, S2.L) as int) as Number,
           stuff(s.Value, 1, S1.Pos + S2.L, '') as Value
    from (select @String+' ') as S(Value)
      cross apply (select patindex('%[0-9]%', S.Value)) as S1(Pos)
      cross apply (select patindex('%[^0-9]%', stuff(S.Value, 1, S1.Pos, ''))) as S2(L)
    union all
    select cast(substring(S.Value, S1.Pos, S2.L) as int),
           stuff(S.Value, 1, S1.Pos + S2.L, '')
    from C as S
      cross apply (select patindex('%[0-9]%', S.Value)) as S1(Pos)
      cross apply (select patindex('%[^0-9]%', stuff(S.Value, 1, S1.Pos, ''))) as S2(L)
    where patindex('%[0-9]%', S.Value) > 0
  )
  select Number
  from C
)

如果您希望字符串中包含超过 100 个数字,则需要使用 option (maxrecursion 0) 调用它。

declare @S varchar(max)
set @S = 'Give me 120 this week and 50 next week'
select number from GetNumbersFromText(@S) option (maxrecursion 0)

【讨论】:

    【解决方案2】:

    @Vikram 的基本想法不错,但他们的查询会将所有数字作为单个项目返回。以下函数返回一个包含在源字符串中找到的单独数字的表:

    CREATE FUNCTION dbo.GetNumbersFromText (@String varchar(2000))
    RETURNS TABLE
    AS
    RETURN (
      WITH NumbersSplit AS (
        SELECT
          C = SUBSTRING(@String, number, 1),
          i = number,
          g = number - ROW_NUMBER() OVER (ORDER BY number)
        FROM master..spt_values
        WHERE type = 'P'
          AND SUBSTRING(@String, number, 1) BETWEEN '0' AND '9'
      ),
      NumbersAssembled AS (
        SELECT
          number = CAST(
            (SELECT C + '' FROM NumbersSplit WHERE g = g.g ORDER BY i FOR XML PATH (''))
            AS varchar(2000)
          )
        FROM NumbersSplit g
        GROUP BY g
      )
      SELECT * FROM NumbersAssembled
    )
    

    注意:此解决方案适用于 SQL Server 2005 或更高版本。

    【讨论】:

      【解决方案3】:

      尝试以下逻辑:

      declare @thestring varchar(50) 
      set @thestring = 'Give me 120 this week and 50 next week' 
      declare @final varchar(50) 
      set @final = '' 
      
      select @final = @final + x.thenum 
      from 
      ( 
          select substring(@thestring, number, 1) as thenum, number 
          from master..spt_values 
          where substring(@thestring, number, 1) like '[0-9]' and type='P'
      ) x 
      order by x.number 
      
      print @final
      

      【讨论】:

        【解决方案4】:

        -- 试试这个代码... -- 没关系!!!


        CREATE FUNCTION [dbo].[udf_ExtractNumberFromString]
        (
            @pInputString VARCHAR(MAX)
        )
        RETURNS VARCHAR(MAX)
        AS
        BEGIN
        
            DECLARE @OutputString varchar(MAX)=''
            DECLARE @string varchar(MAX)
            DECLARE @start INT
            DECLARE @end INT
            DECLARE @len INT
        
            SET @string=@pInputString
            --SET @string = 'the22478ddffafghrty12345TestAddressdd5aa789324-#345'
            SET @string = replace(@string, ' ' , '')
        
            WHILE PATINDEX('%[0-9]%',@string) <> 0
            BEGIN   
                SET @len = len(@string)
            --  PRINT @len
        
                set @start = PATINDEX('%[0-9]%',@string)
            --  PRINT @start
        
                SET @end= PATINDEX('%[^0-9]%',SUBSTRING(@string,@start,@len-@start))
            --  PRINT @end
        
                IF @end=0
                    BEGIN
                        SET @end=@len-@start
                        SET @OutputString=SUBSTRING(@string,@start,@end+1)+'-'+@OutputString
                        BREAK
                    END
                ELSE 
                    BEGIN 
                        SET @OutputString=SUBSTRING(@string,@start,@end-1)+'-'+@OutputString
                        SET @string=SUBSTRING(@string,@end+@start-1,@len-@end)
                    END 
        
                --PRINT @string
        
                --PRINT @Output
                --PRINT '---------------------'
            END
        
            IF LEN(@OutputString)>0
                SET @OutputString=LEFT(@OutputString,LEN(@OutputString)-1) 
            --PRINT @OutputString
        
            RETURN @OutputString
        END
        

        【讨论】:

          【解决方案5】:

          【讨论】:

          • 欢迎来到 Stack Overflow!虽然这在理论上可以回答问题,it would be preferable 在此处包含答案的基本部分,并提供链接以供参考。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-09-29
          • 2021-12-08
          • 1970-01-01
          • 2019-08-06
          • 2021-07-03
          • 1970-01-01
          • 2021-12-23
          相关资源
          最近更新 更多