T-SQL从字符串中选择特定的数字

时间:2016-07-20 18:15:46

标签: sql-server tsql

我需要查询帮助。我有字符串:

"ABC xx DEF SERVERxx ASDF xxx days." 

其中x是数字(0到9可以出现在字符串中的任何位置)。

我对#34;天前的数字感兴趣。"它可以是7到999999 ......

字符串始终以"天结束。"

我试图用这个来做点什么:

 Select Left(SubString(Data, PatIndex(‘%[0-9.-]%’, Data), 8000), PatIndex(‘%[^0-9.-]%’, SubString(Data, PatIndex(‘%[0-9.-]%’, Data), 8000) + ‘X’)-1)

http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/extracting-numbers-with-sql-server/

没有运气,因为它抓住了字符串中的第一个数字。

非常感谢任何帮助。

6 个答案:

答案 0 :(得分:1)

由于最大字符,你可以在天之前得到999999,你可以做的是从右边获取所有11个字符,你还需要numbers表。然后你必须

1.更换空间。
2.使用数字表检查每个字符是否为int 3.最后使用XML路径将多行组合到单行

将其创建为用户定义的函数并尝试使用它..

功能:

;With cte
as
(
select 
  try_convert(int,substring(right(replace(@string,' ',''),11),number,1)) as item
from numbers n
where number<=11
)
select 
STUFF
(
(
select
'' +cast(item as varchar(2))
from cte
where item is not null
for xml path('')
)
,1,0,'')

一些测试:
输入最少数字

declare @string varchar(max)='ABC xx DEF SERVERxx ASDF 1 days'

输出 1

最大输入:
声明@string varchar(max)=&#39; ABC xx DEF SERVERxx ASDF 999999天&#39;

输出 999999

<强>更新  假设dbo.getdata()是我为此创建的标量函数,请在下面选择

select * from test

我所要做的就是

select *,dbo.getdata(columnname) from test

答案 1 :(得分:1)

如果字符串始终以“days”结尾。并且你想要它前面的数字(因此值“days。”是无关紧要的),然后你想要字符串的 reverse 中的第一个数字序列。 / p>

分步显示:

DECLARE @s VARCHAR(MAX);
SET @s = 'ABC 12 DEF SERVER34 ASDF 56789 days.';

DECLARE @t VARCHAR(MAX);
SET @t = REVERSE(@s);

DECLARE @firstDigit BIGINT;
DECLARE @lastDigit BIGINT;
DECLARE @afterDigit VARCHAR(MAX);

SELECT @firstDigit = PATINDEX('%[0-9]%', @t);

SELECT @afterDigit = RIGHT(@t, LEN(@t) - @firstDigit);
SELECT @lastDigit = PATINDEX('%[^0-9]%', @afterDigit) + @firstDigit;

SELECT REVERSE(SUBSTRING(@t, @firstDigit, @lastDigit - @firstDigit + 1));

或者将变量代入最后一行:

DECLARE @s VARCHAR(MAX);
SET @s = 'ABC 12 DEF SERVER34 ASDF 5627891 days.';

SELECT REVERSE(SUBSTRING(REVERSE(@s), PATINDEX('%[0-9]%', REVERSE(@s)), PATINDEX('%[^0-9]%', RIGHT(REVERSE(@s), LEN(REVERSE(@s)) - PATINDEX('%[0-9]%', REVERSE(@s)))) + PATINDEX('%[0-9]%', REVERSE(@s)) - PATINDEX('%[0-9]%', REVERSE(@s)) + 1));

只需用您的列名替换@s的所有七个出现。

如果您需要经常使用该值,最好预处理数据。

答案 2 :(得分:1)

DECLARE @str VARCHAR(max) = 'ABC xx DEF SERVERxx ASDF 203.5 knots' select reverse(SUBSTRING(reverse(@str),charindex(' ',REVERSE(@str)),(charindex(' ',REVERSE(@str),charindex(' ',REVERSE(@str))+1)-charindex(' ',REVERSE(@str)))))

enter image description here

结果= 203.5

答案 3 :(得分:0)

您可以使用下面的简单子字符串函数来实现此目的 DECLARE @s VARCHAR(max) = 'ABC xx DEF SERVERxx ASDF xxx days' DECLARE @locationOfDays INT DECLARE @locationOfASDF INT SELECT @locationOfDays = CHARINDEX('days',@s) SELECT @locationOfASDF = CHARINDEX('ASDF',@s) select @locationOfASDF,@locationOfDays SELECT SUBSTRING(@s,@locationOfASDF+4+1, @locationOfDays-@locationOfASDF-1-4-1) 这种逻辑的方法是首先获得Days和ASDF的位置 这将使用CHARINDEX函数完成并存储在各自的变量中。 然后你可以开始使用SUBSTRING函数来获得你需要的东西,你需要在起始位置添加4 + 1,因为4是ASDF的长度,1是空间的长度,你需要从长度参数中减去相同的长度参数。再次使用子字符串,并为额外空格再增加1个减法。

答案 4 :(得分:0)

虽然效率不高,但是反转字符串,删除前导空格和子字符串将实现此目的:

select reverse(substring(ltrim(replace(reverse(COLUMN), '.syad','')),0, charindex(' ', ltrim(replace(reverse(COLUMN), '.syad','')))))

工作示例:

declare @v as  varchar(500)

select @v = 'ABC xx DEF SERVERxx ASDF 952 days.'

select reverse(substring(ltrim(replace(reverse(@v), '.syad','')),0, charindex(' ', ltrim(replace(reverse(@v), '.syad','')))))

答案 5 :(得分:0)

当他们已经有许多答案已经有效时,我通常不会回答问题,但我认为有一种更简单的方法可以解决这个问题然后在其他答案中引入了什么,所以这是我的溶液:

DECLARE @string varchar(100) = 'ABC 12 DEF SERVER78 ASDF 384684 days.'

SELECT RIGHT(
        LEFT(@String, LEN(@String) - 6), -- remove the ' days.' part
            PATINDEX('%[^0-9]%', 
            REVERSE(
                LEFT(@String, LEN(@String) - 6) -- remove the ' days.' part
            ) -- Reversing this string - it now starts with the number
        ) -- get the index of the first non-digit char after your desired number
    ) 

结果:

 384684

此解决方案的关键是首先删除'天数'。从字符串的末尾开始,使用LEFT()函数。然后,在反向字符串上使用PATINDEX()函数(使用REVERSE())在反向字符串中查找索引的第一个非数字字符。最后,将此值与RIGHT()函数一起使用,仅返回相关的数字。

See live demo here