用于检索特定字符串的SQL语句

时间:2017-12-28 22:15:33

标签: sql sql-server tsql sql-server-2012

我正在尝试从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

4 个答案:

答案 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

您可以看到,我使用CASTREPLACE的技巧将您的字符串转换为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])