查询仅从字符串中获取数字

Avi*_*hta 46 sql sql-server

假设我有这样的数据:

string 1: 003Preliminary Examination Plan   
string 2: Coordination005  
string 3: Balance1000sheet
Run Code Online (Sandbox Code Playgroud)

我期望的输出是

string 1: 003
string 2: 005
string 3: 1000
Run Code Online (Sandbox Code Playgroud)

我想在sql中实现它.请帮忙.提前致谢 :)

Luv*_*Luv 95

首先创造这个 UDF

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
GO
Run Code Online (Sandbox Code Playgroud)

现在使用functionas

SELECT dbo.udf_GetNumeric(column_name) 
from table_name
Run Code Online (Sandbox Code Playgroud)

SQL FIDDLE

我希望这能解决你的问题.

参考

  • 这有效,虽然它提取并连接字符串中的所有数字,所以例如/p-1544937/apartment-flat-6th-october.html将返回15449376,这并不总是你可能正在寻找的 (6认同)
  • 它不处理十进制数字。例如,输入“ 10.95”将返回“ 1095” (2认同)
  • 它真的应该返回一个INT。`返回 CAST(ISNULL(@strAlphaNumeric, 0) AS INT)` (2认同)

Dev*_*art 36

试试这个 -

查询:

DECLARE @temp TABLE
(
      string NVARCHAR(50)
)

INSERT INTO @temp (string)
VALUES 
    ('003Preliminary Examination Plan'),
    ('Coordination005'),
    ('Balance1000sheet')

SELECT LEFT(subsrt, PATINDEX('%[^0-9]%', subsrt + 't') - 1) 
FROM (
    SELECT subsrt = SUBSTRING(string, pos, LEN(string))
    FROM (
        SELECT string, pos = PATINDEX('%[0-9]%', string)
        FROM @temp
    ) d
) t
Run Code Online (Sandbox Code Playgroud)

输出:

----------
003
005
1000
Run Code Online (Sandbox Code Playgroud)

  • 虽然我对这个答案印象深刻并完全解决了OP的问题,但应该注意的是,这个解决方案只适用于连续的数字系列.对于像`Coor60nation005`这样的字符串,它将返回`60`而不是结束'005` (12认同)
  • 它不适用于 (111) 222-3333。我要1112223333 (3认同)
  • 对此答案和鲍达德的评论+1,因为这正是我正在寻找的行为,但接受的答案不是。 (2认同)

小智 13

查询:

DECLARE @temp TABLE
(
    string NVARCHAR(50)
)

INSERT INTO @temp (string)
VALUES 
    ('003Preliminary Examination Plan'),
    ('Coordination005'),
    ('Balance1000sheet')

SELECT SUBSTRING(string, PATINDEX('%[0-9]%', string), PATINDEX('%[0-9][^0-9]%', string + 't') - PATINDEX('%[0-9]%', 
                    string) + 1) AS Number
FROM @temp
Run Code Online (Sandbox Code Playgroud)

  • 这不适用于空格或分隔数字,但可以回答问题。 (2认同)
  • “string + 't'” 是什么? (2认同)

Sim*_*mon 11

我发现这种方法的效果比投票最高的答案快大约 3 倍。创建以下函数 dbo.GetNumbers:

CREATE FUNCTION dbo.GetNumbers(@String VARCHAR(8000))
RETURNS VARCHAR(8000)
AS
BEGIN;
    WITH
        Numbers
    AS (
        --Step 1.
        --Get a column of numbers to represent
        --every character position in the @String.
        SELECT 1 AS Number
        UNION ALL
        SELECT Number + 1
        FROM Numbers
        WHERE Number < LEN(@String)
        )
        ,Characters
    AS (
        SELECT Character
        FROM Numbers
        CROSS APPLY (
                --Step 2.
                --Use the column of numbers generated above
                --to tell substring which character to extract.
                SELECT SUBSTRING(@String, Number, 1) AS Character
            ) AS c
        )
    --Step 3.
    --Pattern match to return only numbers from the CTE
    --and use STRING_AGG to rebuild it into a single string.
    SELECT @String = STRING_AGG(Character,'')
    FROM Characters
    WHERE Character LIKE '[0-9]'

    --allows going past the default maximum of 100 loops in the CTE
    OPTION (MAXRECURSION 8000) 

    RETURN @String
END
GO
Run Code Online (Sandbox Code Playgroud)

测试

测试目的:

SELECT dbo.GetNumbers(InputString) AS Numbers
FROM ( VALUES
         ('003Preliminary Examination Plan') --output: 003
        ,('Coordination005')                 --output: 005
        ,('Balance1000sheet')                --output: 1000
        ,('(111) 222-3333')                  --output: 1112223333
        ,('1.38hello@f00.b4r#\-6')           --output: 1380046
    ) testData(InputString)
Run Code Online (Sandbox Code Playgroud)

性能测试:开始设置测试数据......

--Add table to hold test data
CREATE TABLE dbo.NumTest (String VARCHAR(8000)) 

--Make an 8000 character string with mix of numbers and letters
DECLARE @Num VARCHAR(8000) = REPLICATE('12tf56se',800)

--Add this to the test table 500 times
DECLARE @n INT = 0
WHILE @n < 500
BEGIN
    INSERT INTO dbo.NumTest VALUES (@Num)
    SET @n = @n +1
END
Run Code Online (Sandbox Code Playgroud)

现在测试 dbo.GetNumbers 函数:

SELECT dbo.GetNumbers(NumTest.String) AS Numbers
FROM dbo.NumTest -- Time to complete: 1 min 7s
Run Code Online (Sandbox Code Playgroud)

然后根据相同数据的投票最高的答案测试 UDF 。

SELECT dbo.udf_GetNumeric(NumTest.String)
FROM dbo.NumTest -- Time to complete: 3 mins 12s
Run Code Online (Sandbox Code Playgroud)

dbo.GetNumbers 的灵感

小数点

如果您需要它来处理小数,您可以使用以下任一方法,我发现它们之间没有明显的性能差异。

  • 改成'[0-9]''[0-9.]'
  • 更改Character LIKE '[0-9]'ISNUMERIC(Character) = 1(SQL 将单个小数点视为“数字”)

奖金

WHERE Character LIKE '[0-9]'您可以通过替换以下选项轻松适应不同的要求:

  • WHERE Letter LIKE '[a-zA-Z]' --Get only letters
  • WHERE Letter LIKE '[0-9a-zA-Z]' --Remove non-alphanumeric
  • WHERE Letter LIKE '[^0-9a-zA-Z]' --Get only non-alphanumeric


Tec*_*hDo 10

请试试:

declare @var nvarchar(max)='Balance1000sheet'

SELECT LEFT(Val,PATINDEX('%[^0-9]%', Val+'a')-1) from(
    SELECT SUBSTRING(@var, PATINDEX('%[0-9]%', @var), LEN(@var)) Val
)x
Run Code Online (Sandbox Code Playgroud)

  • **`声明 @var nvarchar(max)='Balance1000sheet123' SELECT LEFT(Val,PATINDEX('%[^0-9]%', Val+'a')-1) from( SELECT SUBSTRING(@var, PATINDEX( '%[0-9]%', @var), LEN(@var)) Val)x`**. 数字不是连续的。 (2认同)

Max*_*nna 8

可以在单行中仅从字符串中获取数字。尝试这个 :

SUBSTRING('your-string-here', PATINDEX('%[0-9]%', 'your-string-here'), LEN('your-string-here'))
Run Code Online (Sandbox Code Playgroud)

注意:仅适用于字符串中的第一个 int,例如:abc123vfg34 返回 123。

  • 如果将整个字符串的长度作为第三个参数传递,它将从找到的第一个数字开始获取字符串的其余部分。你用你的例子尝试过吗?它实际上会返回 `123vfg34` (4认同)

小智 7

适用于 SQL Server 2017 及更高版本的解决方案,使用TRANSLATE

DECLARE @T table (string varchar(50) NOT NULL);

INSERT @T 
    (string)
VALUES 
    ('003Preliminary Examination Plan'),
    ('Coordination005'),
    ('Balance1000sheet');

SELECT 
    result =
        REPLACE(
            TRANSLATE(
                T.string COLLATE Latin1_General_CI_AI, 
                'abcdefghijklmnopqrstuvwxyz', 
                SPACE(26)), 
            SPACE(1), 
            SPACE(0))
FROM @T AS T;
Run Code Online (Sandbox Code Playgroud)

输出:

结果
003
005
1000

该代码的工作原理是:

  1. 用空格替换字符 az(忽略大小写和重音符号)
  2. 用空字符串替换空格。

提供的字符串TRANSLATE可以扩展以包含其他字符。