我正在尝试从Notes列中提取数字。如果数字前面有特定的字符串,我只想要数字。数字长度可以是5或6个字符,将来可能会达到7个或更多。
我需要利用LEFT,RIGHT,CHARINDEX或SUBSTRING的哪种组合来实现这一目标?或者我是否需要完全使用其他东西?我无法找到有效的东西。
Notes列包含许多不同类型的注释,因此一直很困难。
提前致谢。
编辑:对不起,这是一些示例数据和预期输出。
EDIT2:再次抱歉,我应该让样本数据更加清晰。有多个号码,但我只想要前面带有'帐号#'的数字。
Sample Data Output
'Account #12345' 12345
'Account #123456' 123456
'Random #12345' NULL
'Account #1234567' 1234567
'12345' NULL
'Random' NULL
答案 0 :(得分:1)
这确保'帐号#'后面有5位数字,并在更长时间后要求输入isnumeric。这不是您的要求的100%,而是一种方法。 Isnumeric函数以特殊方式工作 https://docs.microsoft.com/en-us/sql/t-sql/functions/isnumeric-transact-sql
--len('Account #') is 9
select case when Notes like 'Account #[0-9][0-9][0-9][0-9][0-9]%'
and isnumeric(right(Notes,len(Notes)-9) )=1 then right(Notes,len(Notes)-9)
else null end
from myTable
对于SQLServer 2012+,请使用try_parse https://docs.microsoft.com/en-us/sql/t-sql/functions/try-parse-transact-sql
select case when Notes like 'Account #[0-9][0-9][0-9][0-9][0-9]%'
and isnumeric(try_parse(right(Notes,len(Notes)-9) as bigint ))=1
then right(Notes,len(Notes)-9) else null end
from myTable
SQLFIDDLE http://sqlfiddle.com/#!6/cd617/2
答案 1 :(得分:1)
你可以试试这个:
DECLARE @dummyTbl TABLE(YourString VARCHAR(100));
INSERT INTO @dummyTbl VALUES
('Account #12345')
,('Account #123456')
,('Random # note')
,('Account #1234567');
WITH Casted AS
(
SELECT YourString
,CAST('<x>' + REPLACE(YourString,' #','</x><x>') + '</x>' AS XML) toXML
FROM @dummyTbl
)
SELECT YourString
,toXML
,toXML.value('x[1]','nvarchar(max)') AS KeyText
,toXML.value('x[2] cast as xs:int?','int') AS NumberIfCastable
FROM Casted;
结果
YourString toXML KeyText NumberIfCastable
Account #12345 <x>Account</x><x>12345</x> Account 12345
Account #123456 <x>Account</x><x>123456</x> Account 123456
Random # note <x>Random</x><x> note</x> Random NULL
Account #1234567 <x>Account</x><x>1234567</x> Account 1234567
您可以看到,我使用CAST
和REPLACE
的技巧将您的字符串转换为XML,允许分别处理每个部分。 XPath
到第一个元素x[1]
会返回帐户或随机,而第二个x[2]
会返回该数字。
我使用的第二个技巧是XQuery
隐含的 try_cast 值的能力。如果该值无法转换为xs:int?
,则会以NULL
的形式返回。
答案 2 :(得分:1)
我会使用substring()
patindex()
函数来获取数值
SELECT sampledata, SUBSTRING(sampledata, PATINDEX('%[1-9]%', SampleData),
case
when(LEN(sampledata)-PATINDEX('%[1-9]%', SampleData)+1) > LEN(SampleData)
then 0
else LEN(sampledata)-PATINDEX('%[1-9]%', SampleData)+1
end) numericvalues
FROM table;
修改强>
提出问题后更改问题很粗鲁。它可以使答案无效,而答案又可以吸引投票。
嗯,我根据编辑的帖子更新了答案。
select sampledata,
case
when patindex('%Account #%', sampledata) > 0
then SUBSTRING(sampledata, PATINDEX('%[1-9]%', sampledata), LEN(sampledata)-PATINDEX('%[1-9]%', sampledata)+1)
end [Output]
from table
结果:
Sample Data Output
'Account #12345' 12345
'Account #123456' 123456
'Random #12345' NULL
'Account #1234567' 1234567
'12345' NULL
'Random' NULL
答案 3 :(得分:1)
这应该这样做。
SELECT YT.[Sample Data],
S2.[Output]
FROM YourTable YT
CROSS APPLY (SELECT 'Account #') S(S)
CROSS APPLY (SELECT CASE
WHEN CHARINDEX(S.S, [Sample Data]) > 0
THEN SUBSTRING([Sample Data], LEN(S.S) + CHARINDEX(S.S, [Sample Data]), 8000)
END) S1(StringWithNumberAtStart)
CROSS APPLY (SELECT LEFT(StringWithNumberAtStart,
PATINDEX('%[^0-9]%', StringWithNumberAtStart + 'X'))) S2([Output])