我需要在字符串中获取第一个数字:
我怎样才能用SQL做到这一点?
答案 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 |
+---------+-----+