如何获取SQL字符串中的第一个数字

时间:2017-11-13 11:26:07

标签: sql sql-server

我需要在字符串中获取第一个数字:

  • 1-2-3 - > 1
  • 45-6 - > 45
  • 777 8 - > 777
  • 9ab10 - > 9

我怎样才能用SQL做到这一点?

4 个答案:

答案 0 :(得分:1)

您可以使用PATINDEX函数搜索第一个非数字字符

SELECT LEFT(s,ISNULL(NULLIF(PATINDEX('%[^0-9]%',s),0)-1,LEN(s)))
FROM
  (
    VALUES
      ('1-2-3'),
      ('45-6'),
      ('777 8'),
      ('9ab10'),
      ('123'),
      ('abc')
  ) v(s)

如果字符串以非数字前缀开头,那么我们可以首先删除此前缀

SELECT
  LEFT(s,ISNULL(NULLIF(PATINDEX('%[^0-9]%',s),0)-1,LEN(s)))
FROM
  (
    SELECT
      -- delete non-numberic prefix
      IIF(s NOT LIKE '[0-9]%',STUFF(s,1,PATINDEX('%[0-9]%',s)-1,''),s) s
    FROM
      (
        VALUES
          ('1-2-3'),
          ('45-6'),
          ('777 8'),
          ('9ab10'),
          ('123'),
          ('abc'),
          ('#12test'),
          ('No999-888')
      ) v(s)
  ) q

答案 1 :(得分:0)

Turning a Comma Separated string into individual rows它可以帮助您分隔字符串'然后按IsNumber检查

答案 2 :(得分:0)

您还可以使用substring() patindex()函数来获取第一个数值

SELECT SUBSTRING(DATA, 1, PATINDEX('%[^0-9]%', DATA)-1) FROM <table_name>

结果:

1
45
777
9

答案 3 :(得分:0)

这可以通过一些字符串拆分和窗口函数来实现,它采用完全基于集合的方式,不使用用户定义的函数:

-- Test Data
declare @v table(v nvarchar(10));
insert into @v values('1-2-3'),('45-6'),('777 8'),('a9b10'),('abc9b10'),('123'),('abc');

            -- Create table with 10 rows in it
with t(t) as (select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1)
            -- Self join this table 6 times to cover very large string lengths (10*10*10*10*10*10 = 1,000,000 rows) and row number to get incremental list
    ,n(n) as (select top (select max(len(v)) from @v) row_number() over (order by (select null)) from t t1,t t2,t t3,t t4,t t5,t t6)
            -- Split the strings using this list of incremental numbers and use window functions to determine:
    ,v    as (select v.v
                    ,n.n
                        -- The actual character at this position
                    ,substring(v.v,n.n,1) as l
                        -- Is it numeric?
                    ,case when substring(v.v,n.n,1) like '[0-9]' then 1 else 2 end as i
                        -- Order all the numeric values
                    ,rank() over (partition by v.v order by case when substring(v.v,n.n,1) like '[0-9]' then 1 else 2 end, n.n) as c
                        -- Group the numeric rows together by summing up the numeric checks
                    ,sum(case when substring(v.v,n.n,1) like '[0-9]' then 0 else 1 end) over (partition by v.v order by n.n) as g
              from n
                  join @v as v
                      on n.n <= len(v.v)
             )
select v.v
                -- Use a FOR XML statement to concatenate the additional values together
      ,v.l + isnull((select '' + v2.l
                    from v as v2
                    where v.v = v2.v
                        and v.n < v2.n
                        and (v2.c = 1
                            or v.g = v2.g
                            )
                    for xml path('')
                    ),'') as n
from v
where c = 1     -- Only select the first grouping of numbers
    and i = 1
order by v.v;

输出:

+---------+-----+
|    v    |  n  |
+---------+-----+
| 123     | 123 |
| 1-2-3   |   1 |
| 45-6    |  45 |
| 777 8   | 777 |
| a9b10   |   9 |
| abc9b10 |   9 |
+---------+-----+