根据最后一个charindex的出现来解析字符串

时间:2017-07-17 11:03:32

标签: sql-server tsql sql-server-2016

我有以下字符串:

Hello World (111)
Welcome to the World (GI 135) (222)
Another Hello World String (ID 12) (141) (333)

我需要解析最后一个括号中的值,因此输出为:

111
222
333

我不知道如何动态地使它总是得到最后括号的charindex / patindex。这就是我到目前为止所做的:

DECLARE @str TABLE ( varString VARCHAR(100) );

INSERT  INTO @str
        ( varString )
VALUES  ( 'Hello World (111)' ),
        ( 'Welcome to the World (GI 135) (222)' ),
        ( 'Another Hello World String (ID 12) (141) (333)' );

SELECT  varString
       ,Parsed = CASE WHEN PATINDEX('%[0-9])%', varString) - PATINDEX('%([0-9]%', varString) > 0 THEN SUBSTRING(varString, PATINDEX('%([0-9]%', varString) + 1, PATINDEX('%[0-9])%', varString) - PATINDEX('%([0-9]%', varString))
                      ELSE NULL
                 END
FROM    @str;

但它仅适用于第一种情况Hello World (111)

4 个答案:

答案 0 :(得分:0)

没关系。我有它。

SELECT  varString
       ,Parsed = REVERSE(SUBSTRING(REVERSE(varString), 2, CHARINDEX('(', REVERSE(varString)) - 2))
FROM    @str;

但是如果基于查找最后一个charindex的出现有任何其他解决方案,我将很高兴,如果你分享它。

答案 1 :(得分:0)

您可以使用反向并获取最新信息,如下所示:

Select *, Replace(substring(txt,len(txt) - charindex('(', Reverse(txt))+2, len(txt)), ')', '')
from #yourtext

答案 2 :(得分:0)

将字符串作为xml处理可能是获取最后一个的另一个解决方案,基本上用标签替换括号,强制转换为xml并获取最后一个元素:

select cast(replace(replace(varstring,'(','<n>'),')','</n>') as xml).query('//n[last()]/text()')

答案 3 :(得分:0)

您发布的解决方案要求字符串以右括号结束,即使尾随空格也会将其终止。

XML解决方案非常出色(使用last()函数@Jayvee),但通过添加或减去单个右括号或左括号可以轻松实现。

以下两个解决方案将起作用,并且可以由想要检索的人员轻松修改,第一个数字组或所有数字组。第一个解决方案使用PatterSplitCM,第二个解决方案使用NGrams8K。更新了以下两个示例数据和解决方案。

DECLARE @str TABLE (stringId int identity, varString VARCHAR(100) );

INSERT INTO @str(varstring)
VALUES  ( 'Hello World (111)' ),
        ( 'Welcome to the World (GI 135) (222)' ),
        ( 'Another Hello World String (ID 12) (141) (333)' ),
        ( 'Hello World (55555).' ), -- added a period (.)
        ( 'Welcome to the World (GI 135) (999) and smile (:' ), -- add unclosed parentheses,
        ( 'Another Hello World String (ID 1212) (14111) (33333)) ' ), -- ends with a space
        ('No numbers here. Sorry.')

-- SOLUTION #1 (using PatternSplitCM)
SELECT stringId, varString, item 
FROM 
(
  SELECT stringId, varString, item, 
         rn = ROW_NUMBER() OVER (PARTITION BY varstring ORDER BY itemnumber DESC)
  FROM @str
  CROSS APPLY dbo.PatternSplitCM(varString, '[0-9]')
  WHERE [Matched] = 1
) x
WHERE rn = 1
--ORDER BY stringId;
;
-- SOLUTION #2 (using NGrams8K)
SELECT stringId, varString, item 
FROM 
(
  SELECT stringId, varString,
         item = SUBSTRING
                (
                  varString, 
                  position+1, 
                  CHARINDEX(')', varString, position+1)-(position+1)
                ),
         rn  = ROW_NUMBER() OVER (PARTITION BY varstring ORDER BY position DESC)
  FROM @str
  CROSS APPLY dbo.ngrams8k(varString,1)
  WHERE token = '('
  AND CHARINDEX(')', varString, position+1) > 0 -- exclude strings without closing parenthesis 
) x
WHERE rn = 1

每个查询返回:

stringId  varString                                             item  
--------- ----------------------------------------------------- ----------
1         Hello World (111)                                     111
2         Welcome to the World (GI 135) (222)                   222
3         Another Hello World String (ID 12) (141) (333)        333
4         Hello World (55555).                                  55555
5         Welcome to the World (GI 135) (999) and smile (:      999
6         Another Hello World String (ID 1212) (14111) (33333)) 33333