2010-03-17 4 views
2

J'ai une colonne de texte varchar (4000) avec le texte:SQL Server: remplacer la séquence de mêmes caractères à l'intérieur Champ de texte (TSQL seulement)

'aaabbaaacbaaaccc'

et je dois enlever tous les caractères en double - donc seulement une séquence de gauche:

'abacbac' 

Il ne doit pas être une fonction, une procédure ou CLR - solution Regex. Seul vrai SQL sélectionner.

Actuellement, je pense à l'utilisation de la clause récurrente WITH avec le remplacement 'aa' -> 'a', 'bb' -> 'b', 'cc' -> 'c'.

La récursivité devrait donc être cyclée jusqu'à ce que toutes les séquences dupliquées de ces caractères soient remplacées.

Avez-vous une autre solution, peut-être plus performante? PS: J'ai parcouru ce site à propos de différents exemples de remplacement - ils ne correspondaient pas à ce cas.

+0

Cela ressemble à une question de devoirs. Pourquoi pas de fonctions? – CResults

+1

Ouais, genre de test. Mais je veux vérifier si la variante "WITH" récursive est OK. Pas de fonctions car je sais comment implémenter cela avec fonction. Il est intéressant de trouver la meilleure approche SQL-Native. – zmische

+0

Puis-je ajouter une table auxiliaire? Ce sera très petit mais j'ai, oh je ne sais pas, 4000 lignes :) – CResults

Répondre

3

En supposant une définition de table de

CREATE TABLE myTable(rowID INT IDENTITY(1,1), dupedchars NVARCHAR(4000)) 

et des données ..

INSERT INTO myTable 
     SELECT 'aaabbaaacbaaaccc' 
     UNION 
     SELECT 'abcdeeeeeffgghhaaabbbjdduuueueu999whwhwwwwwww' 

cette requête répond à vos critères

WITH Numbers(n) 
     AS 
     ( SELECT 1 AS n 
      UNION ALL 
      SELECT (n + 1) AS n 
       FROM Numbers 
      WHERE n < 4000 
     ) 
    SELECT rowid, 
     ( SELECT CASE 
      WHEN SUBSTRING(dupedchars,n2.n,1) = SUBSTRING(dupedchars+' ',n2.n+1,1) THEN '' 
      ELSE SUBSTRING(dupedchars,n2.n,1) 
      END AS [text()] 
      FROM myTable t2,numbers n2 
      WHERE n2.n <= LEN(dupedchars) 
      AND t.rowid = t2.rowid 
      FOR XML path('') 
     ) AS deduped 
    FROM myTable t 
    OPTION(MAXRECURSION 4000) 

Sortie

rowid deduped 
    1 abacbac 
    2 abcdefghabjdueueu9whwhw 
+0

CResults: c'est fantastique!)) Je pensais presque à peu près la même chose. Mais approche différente. Le vôtre est plus universel! Merci! Et qu'en est-il des problèmes de performance pour une table de plus de 100 000 lignes ??? Ai-je raison de dire que c'est LA SEULE option en utilisant Native SQL? – zmische

+0

Pour autant de lignes, le temps d'exécution est d'environ 10 secondes. Les alternatives (que je regardais à l'origine) seraient d'avoir une alternative physique à Numbers avec un index. Vous * pouvez * obtenir une certaine amélioration de cela mais la partie lente de la requête est le du-duping - toute manipulation de chaîne de ce type aura une surcharge de vitesse. – CResults

+0

Notez que les 10 secondes sont basées sur des longueurs de chaîne similaires à celles indiquées ci-dessus. Comme suggéré, le temps est impliqué dans le dédoublement. Définissez tous vos champs à 4000 caractères et vous regardez environ 1000 résultats par minute. Si vous avez des valeurs en double dans vos champs, vous obtiendrez une optimisation en fournissant uniquement les valeurs uniques à cette requête. – CResults

Questions connexes