I have a table stat
that is VARCHAR type and would like to grab all the numbers within it individually. For example, if a specific record in the column has the value 12 to 24 MONTHS Fl
then I would like to grab 12 and 24 separately. I've seen other posts where the numbers end up grouped together and would be 1224
in this case, but how could I do the aforementioned separating of the numbers? Given that I do not know the number of digits in each of the numbers, I was wondering how best to do this. Thanks
For an example like 12 to 24 months APY1.8semi
the output would need to be 12
,24
and 1.8
, but to be clear there are only whole numbers and there aren't any .
characters in the column.
CodePudding user response:
First we create this function.
create function [dbo].[GetNumbersFromText](@String varchar(2000))
returns table as return
(
with C as
(
select cast(substring(S.Value, S1.Pos, S2.L) as decimal(10,2)) 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 decimal(10,2)),
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
)
Then we use it in our query.
select string_agg(number, ', ') as result from GetNumbersFromText('12 to 24 months APY1.8semi')
result |
---|
12.00, 24.00, 1.80 |
CodePudding user response:
I shamelessly copied this answer from another post but made a small modification to preserve your spaces. This one is essentially replacing letters with the @ symbol, then replacing the @ symbol.
select id, REPLACE(TRANSLATE([comments], 'abcdefghijklmnopqrstuvwxyz ()- ,# ', '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'), '@', ' ')
from my_data
id | (No column name) |
---|---|
1 | 12 24 |
2 | 12 24 1.8 |
Or if you would prefer results as a tall table, then you could apply the string_split
function.
select id, value from (
select id, ca.value
from my_data
cross apply string_split (REPLACE(TRANSLATE([comments], 'abcdefghijklmnopqrstuvwxyz ()- ,# ', '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'), '@', ','), ',')ca
)z
where value <> ''
id | value |
---|---|
1 | 12 |
1 | 24 |
2 | 12 |
2 | 24 |
2 | 1.8 |