提取特定单词前的数字,包括浮点数的SQL查询。

huangapple go评论95阅读模式
英文:

SQL Query to extract the numbers before a specific word, including floating point numbers

问题

  1. String 4: '3.9'
英文:

I have data like this:

  1. String 1: 'Random Text 3 Random 568 Text 5.5 Test Random Text 345'
  2. String 2: 'Random Text 3 Test Text Random'
  3. String 3: 'Random Text 777 Random Text'

The output I expect is:

  1. String 1: '5.5'
  2. String 2: '3'
  3. String 3: Nothing should output

And this works using the below code, provided from here: https://stackoverflow.com/a/75923063/10787041

  1. CREATE FUNCTION GetNumberBeforeStringTest
  2. (
  3. @stringToParse varchar(100)
  4. )
  5. RETURNS VARCHAR(100)
  6. AS
  7. BEGIN
  8. DECLARE @testIndex INT = PATINDEX('%test%', @stringToParse);
  9. IF @testIndex = 0 RETURN NULL;
  10. DECLARE @s1 VARCHAR(100) = REVERSE(TRIM(SUBSTRING(@stringToParse, 0, @testIndex)))
  11. DECLARE @s2 VARCHAR(100) = REVERSE(TRIM(SUBSTRING(@s1, 0, CHARINDEX(' ', @s1))))
  12. IF TRY_CAST(@s2 AS decimal) IS NULL
  13. RETURN NULL;
  14. RETURN @s2;
  15. END
  16. GO

I've noticed that when there is a string with brackets and a floating point the function doesn't work. An example would be:

  1. String 4: 'Random Text (3.9 Test) Text Random'

Would it be possible to tell me how to edit the function to also be able to extract the number from a string that includes floating point numbers and a bracket, if this is having an affect on the function not working?

Thanks

答案1

得分: 2

请尝试以下解决方案。它将从SQL Server 2017开始起作用,因为使用了T-SQL的TRANSLATE()函数,无需任何UDF函数。

SQL

  1. -- DDL and sample data population, start
  2. DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, tokens VARCHAR(MAX));
  3. INSERT @tbl (tokens) VALUES
  4. ('Random Text 3 Random 568 Text 5.5 Test Random Text 345'),
  5. ('Random Text 3 Test Text Random'),
  6. ('Random Text 777 Random Text'),
  7. ('Random Text 777 Random Test'),
  8. ('Random Text (3.9 Test) Text Random');
  9. -- DDL and sample data population, end
  10. DECLARE @separator CHAR(1) = SPACE(1);
  11. SELECT *
  12. , c.query('for $x in /root/r
  13. let $pos := count(/root/r[. << $x]) + 1
  14. return if (xs:decimal($x) instance of xs:decimal (: filter out non-digits :)
  15. and /root/r[$pos + 1]/text()="Test") then $x
  16. else ()').value('.','VARCHAR(MAX)') AS result
  17. FROM @tbl AS t
  18. CROSS APPLY (SELECT TRY_CAST('<root><r><![CDATA[' +
  19. REPLACE(TRANSLATE(tokens,')(',' '), @separator, ']]></r><r><![CDATA[') +
  20. ']]></r></root>' AS XML)) AS t1(c)
  21. ORDER BY ID;

Output

ID tokens result
1 Random Text 3 Random 568 Text 5.5 Test Random Text 345 5.5
2 Random Text 3 Test Text Random 3
3 Random Text 777 Random Text
4 Random Text 777 Random Test
5 Random Text (3.9 Test) Text Random 3.9
英文:

Please try the following solution.

It will work starting from SQL Server 2017 onwards due to use of the T-SQL TRANSLATE() function

No need in any UDF function.

SQL

  1. -- DDL and sample data population, start
  2. DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, tokens VARCHAR(MAX));
  3. INSERT @tbl (tokens) VALUES
  4. (&#39;Random Text 3 Random 568 Text 5.5 Test Random Text 345&#39;),
  5. (&#39;Random Text 3 Test Text Random&#39;),
  6. (&#39;Random Text 777 Random Text&#39;),
  7. (&#39;Random Text 777 Random Test&#39;),
  8. (&#39;Random Text (3.9 Test) Text Random&#39;);
  9. -- DDL and sample data population, end
  10. DECLARE @separator CHAR(1) = SPACE(1);
  11. SELECT *
  12. , c.query(&#39;for $x in /root/r
  13. let $pos := count(/root/r[. &lt;&lt; $x]) + 1
  14. return if (xs:decimal($x) instance of xs:decimal (: filter out non-digits :)
  15. and /root/r[$pos + 1]/text()=&quot;Test&quot;) then $x
  16. else ()&#39;).value(&#39;.&#39;,&#39;VARCHAR(MAX)&#39;) AS result
  17. FROM @tbl AS t
  18. CROSS APPLY (SELECT TRY_CAST(&#39;&lt;root&gt;&lt;r&gt;&lt;![CDATA[&#39; +
  19. REPLACE(TRANSLATE(tokens,&#39;)(&#39;,SPACE(2)), @separator, &#39;]]&gt;&lt;/r&gt;&lt;r&gt;&lt;![CDATA[&#39;) +
  20. &#39;]]&gt;&lt;/r&gt;&lt;/root&gt;&#39; AS XML)) AS t1(c)
  21. ORDER BY ID;

Output

ID tokens result
1 Random Text 3 Random 568 Text 5.5 Test Random Text 345 5.5
2 Random Text 3 Test Text Random 3
3 Random Text 777 Random Text
4 Random Text 777 Random Test
5 Random Text (3.9 Test) Text Random 3.9

答案2

得分: 1

  1. DECLARE @s1 VARCHAR(100) = REVERSE(REPLACE(REPLACE(TRIM(SUBSTRING(@stringToParse, 0, @testIndex)),'(',''),')',''))
英文:

You could remove any brackets within the string using the REPLACE function, the S1 line would look like this instead:

  1. DECLARE @s1 VARCHAR(100) = REVERSE(REPLACE(REPLACE(TRIM(SUBSTRING(@stringToParse, 0, @testIndex)),&#39;(&#39;,&#39;&#39;),&#39;)&#39;,&#39;&#39;))

答案3

得分: 1

请查看这个基于不同前提的替代内联表值函数。

它返回一个表,在处理一组行时性能会更好。

函数:

  1. create or alter function dbo.GetNumberBeforeStringTest(@str varchar(100))
  2. returns table as
  3. return select [value] = Iif(Try_Cast(n.v as decimal) is null, null, n.v)
  4. from (select @str s)t
  5. cross apply(values(NullIf(CharIndex('test', t.s), 0)-1))test(p)
  6. cross apply(values(left(t.s, test.p)))l(p)
  7. cross apply(values(patindex('%[^0-9.]%', Trim(Reverse(l.p)))))x(p)
  8. cross apply(values(Right(l.p, x.p)))n(v);

使用方式:

  1. select t.col, v.[value]
  2. from t
  3. cross apply dbo.GetNumberBeforeStringTest(col)v;

以及 a Fiddle demo

英文:

Please have a look at this alternative inline-table-valued function that works on a different premise.

It returns a table which will be considerably more performant when used for a set of rows.

The function:

  1. create or alter function dbo.GetNumberBeforeStringTest(@str varchar(100))
  2. returns table as
  3. return select [value] = Iif(Try_Cast(n.v as decimal) is null, null, n.v)
  4. from (select @str s)t
  5. cross apply(values(NullIf(CharIndex(&#39;test&#39;, t.s), 0)-1))test(p)
  6. cross apply(values(left(t.s, test.p)))l(p)
  7. cross apply(values(patindex(&#39;%[^0-9.]%&#39;, Trim(Reverse(l.p)))))x(p)
  8. cross apply(values(Right(l.p, x.p)))n(v);

And to use:

  1. select t.col, v.[value]
  2. from t
  3. cross apply dbo.GetNumberBeforeStringTest(col)v;

And a Fiddle demo

huangapple
  • 本文由 发表于 2023年4月20日 03:38:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76058234.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定