2017-07-17 1 views
0

J'ai les chaînes suivantes:chaîne Parse basée sur la présence de la dernière charindex

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

où je dois analyser les valeurs dans les dernières parenthèses, de sorte que la sortie serait:

111 
222 
333 

Je ne suis pas sûr de savoir comment le faire dynamiquement pour toujours obtenir charindex/patindex pour les toutes dernières parenthèses. Voilà ce que j'ai jusqu'à présent:

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; 

mais il ne fonctionne que pour le premier cas Hello World (111).

Répondre

0

Nevermind. Je l'ai. Mais s'il y a une autre solution basée sur trouver l'occurrence du dernier charindex, je serai heureux si vous le partagez.

0

Vous pouvez utiliser inverse et obtenir la dernière comme ci-dessous:

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

manipulation de la chaîne comme XML pourrait être une autre solution pour obtenir le dernier, remplaçant essentiellement les crochets par des balises, jeté comme xml et obtenir la dernière élément:

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

C'est assez agréable. Merci. Bonne idée. – DNac

0

la solution que vous avez affichée nécessite la chaîne à la fin avec une parenthèse droite, même un espace de fuite tuera.

La solution XML est excellente (utilisation brillante de la fonction last() @Jayvee) mais se casse facilement en ajoutant ou en soustrayant une seule parenthèse droite ou gauche.

Voici deux solutions qui fonctionnent et peuvent être facilement modifiés par des personnes qui cherchent à récupérer dire, le groupe premier de nombres ou tous des ensembles de nombres. La première solution utilise PatterSplitCM et la seconde utilise NGrams8K. Données d'échantillon mises à jour et les deux solutions ci-dessous.

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 

Chaque requête renvoie:

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 
+0

Merci pour toute autre suggestion. Dans mon prod, je prends aussi le code comme: CASE WHEN varString LIKE '% ([0-9]% [0-9])%' ALORS ... donc ça devrait le protéger du problème que vous avez mentionné. – DNac