I have business requirement as keep only numeric values and make rest as null. Like below
Result
>4.2
<6.0
5.0 is max
dup
1
OUTPUT as
Result
4.2
6.0
5.0
NULL
1
I have business requirement as keep only numeric values and make rest as null. Like below
Result
>4.2
<6.0
5.0 is max
dup
1
OUTPUT as
Result
4.2
6.0
5.0
NULL
1
Please try the following solution.
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, tokens VARCHAR(100));
INSERT INTO @tbl (tokens) VALUES
('>4.2'),
('<6.0'),
('5.0 is max'),
('dup'),
('1');
-- DDL and sample data population, end
DECLARE @separator CHAR(1) = SPACE(1);
SELECT ID, tokens
, c.query('<root>
{
for $x in /root/r
return if (xs:decimal($x) instance of xs:decimal) then $x
else () (: filter out non-decimals :)
}
</root>').value('(/root/r/text())[1]','VARCHAR(10)') as result
FROM @tbl
CROSS APPLY (SELECT TRY_CAST('<root><r><![CDATA[' +
REPLACE(REPLACE(REPLACE(tokens,'>',''),'<',''), @separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML)) AS t(c);
Output
+----+------------+--------+
| ID | tokens | result |
+----+------------+--------+
| 1 | >4.2 | 4.2 |
| 2 | <6.0 | 6.0 |
| 3 | 5.0 is max | 5.0 |
| 4 | dup | NULL |
| 5 | 1 | 1 |
+----+------------+--------+
SQL Server is not optimal for this, but this logic should do what you want:
select *,
left(v2.str, patindex('%[^.0-9]%', v2.str + ' ') - 1)
from (values ('5.0 is max')) v(str) cross apply
(values (stuff(v.str, 1, patindex('%[0-9]%', v.str) - 1, ''))) v2(str);
Here is a db<>fiddle.
One approach you could try is using a user-defined function to strip out the numbers only from your strings.
It won't be performant over a very large dataset, but is simple to implement and might work for you depending on your requirements.
create or alter function [dbo].[NumbersOnly](@str varchar(100))
returns varchar(100)
as
begin
declare @len smallint=Len(@str), @i smallint=0, @result varchar(100)=''
while @i <=@len
begin
if Ascii(Substring(@str,@i,1)) in (46,48,49,50,51,52,53,54,55,56,57)
set @result=@result + Substring(@str,@i,1)
set @i=@i+1
end
return @result
end
go
Then just use it against your data:
select NullIf(dbo.NumbersOnly(Result),'') as Result
from table
See Example Fiddle
cross apply() using string_split() unfortunately SQL Server doesn't provide a method to guarantee ordering, so a solution using this method also requires a custom set-based string split method, which is just a lot of gumph! Hence why I said this might be useful to you if it works for your particular use-case; I use it in various projects where it's required on no more than 1-2k rows with no issues.You can use Patreplace8K which makes this stuff easy. Here I'm saying "remove anything that matches this pattern, [0-9.]; e.g. anything that is not a number or a dot. This is the fastest function for this type of thing.
--==== Sample Data
DECLARE @table TABLE (SomeString VARCHAR(20));
INSERT @table VALUES('>4.2'),('<6.0'),('5.0 is max'),('dup'),('1');
--==== Solution using Patreplace
SELECT t.SomeString, pr.NewString
FROM @table AS t
CROSS APPLY samd.patReplace8K(t.SomeString,'[^0-9.]','') AS pr;
Results:
SomeString NewString
------------- ---------------
>4.2 4.2
<6.0 6.0
5.0 is max 5.0
dup NULL
1 1