178 votes

De meilleures techniques pour tailler les zéros non significatifs dans SQL Server?

J'ai été en utilisant ce depuis un certain temps:

SUBSTRING(str_col, PATINDEX('%[^0]%', str_col), LEN(str_col))

Toutefois, récemment, j'ai trouvé un problème avec des colonnes avec tous les "0" de caractères comme '00000000', car il ne trouve un non-"0" caractère de match.

Une autre technique que j'ai vu est à utiliser TRIM:

REPLACE(LTRIM(REPLACE(str_col, '0', ' ')), ' ', '0')

Cela a un problème si il y a des espaces, car ils seront transformés en "0"quand les espaces sont transformés en "0".

J'essaie d'éviter un scalaire UDF. J'ai trouvé beaucoup de problèmes de performances avec les fonctions définies par l'utilisateur dans SQL Server 2005.

330voto

Arvo Points 4151
SUBSTRING(str_col, PATINDEX('%[^0]%', str_col+'.'), LEN(str_col))

53voto

Quassnoi Points 191041

Pourquoi ne pas vous venez de convertir la valeur en INTEGER puis retour à l' VARCHAR?

SELECT  CAST(CAST('000000000' AS INTEGER) AS VARCHAR)

--------
       0

14voto

MikeTeeVee Points 3578

D'autres réponses ici, pour ne pas prendre en considération si vous avez tous les zéro (ou même un seul zéro).
Certains toujours par défaut est une chaîne vide à zéro, ce qui est mauvais quand il est censé rester vide.
Re-lecture de la question d'origine. Ceci répond à ce que l'Interlocuteur veut.

Solution (avec les données de l'échantillon):

SELECT O.Type, O.Value, Parsed.Value[WrongValue],
       (CASE WHEN CHARINDEX('0', T.Value)  > 0--If there's at least one zero.
              AND LEN(Parsed.Value) = 0--And the trimmed length is zero.
             THEN '0' ELSE Parsed.Value END)[FinalValue],
       (CASE WHEN CHARINDEX('0', T.Value)  > 0--If there's at least one zero.
              AND LEN(Parsed.TrimmedValue) = 0--And the trimmed length is zero.
             THEN '0' ELSE LTRIM(RTRIM(Parsed.TrimmedValue)) END)[FinalTrimmedValue]
  FROM 
  (
    VALUES ('Null', NULL), ('EmptyString', ''),
           ('Zero', '0'), ('Zero', '0000'), ('Zero', '000.000'),
           ('Spaces', '    0   A B C '), ('Number', '000123'),
           ('AlphaNum', '000ABC123'), ('NoZero', 'NoZerosHere')
  ) AS O(Type, Value)--O is for Original.
  CROSS APPLY
  ( --This Step is Optional.  Use if you also want to remove leading spaces.
    SELECT LTRIM(RTRIM(O.Value))[Value]
  ) AS T--T is for Trimmed.
  CROSS APPLY
  ( --From @CadeRoux's Post.
    SELECT SUBSTRING(O.Value, PATINDEX('%[^0]%', O.Value + '.'), LEN(O.Value))[Value],
           SUBSTRING(T.Value, PATINDEX('%[^0]%', T.Value + '.'), LEN(T.Value))[TrimmedValue]
  ) AS Parsed

Résultats:

MikeTeeVee_SQL_Server_Remove_Leading_Zeros

Résumé:

Vous pouvez utiliser ce que j'ai ci-dessus pour un retrait de la pointe de zéro.
Si vous prévoyez de réutiliser un lot, puis le placer dans un Inline-Table-Fonction (ITVF).
Vos préoccupations au sujet des problèmes de performances avec l'UDF est compréhensible.
Toutefois, ce problème ne s'applique à Tous-Scalaire-Fonctions et Multi-Déclaration de la Table des Fonctions.
À l'aide de ITVF est parfaitement bien.

J'ai le même problème avec notre de la 3e Partie de la base de données.
Avec des Alpha-Numérique des champs beaucoup sont entrés dans sans les espaces, dang les humains!!!
Cela rend rejoint impossible sans le nettoyage de la manque à la pointe des zéros.

Conclusion:

Au lieu de supprimer l'avant-zéros, vous pouvez envisager de rembourrage votre garnis de valeurs avec des zéros lorsque vous faites vos jointures.
Je pense que ce serait plus rapide et moins complexe.

SELECT RIGHT('0000000000' + LTRIM(RTRIM(NULLIF(' 0A10  ', ''))), 10)--0000000A10
SELECT RIGHT('0000000000' + LTRIM(RTRIM(NULLIF('', ''))), 10)--NULL --When Blank.

5voto

Joel Coehoorn Points 190579

Au lieu d'un espace de remplacer le 0 par un "rare" les espaces de caractère qui ne devrait pas normalement être dans la colonne de texte. Un saut de ligne est probablement assez bon pour une colonne de ce genre. Ensuite, vous pouvez LTrim normalement et remplacer le caractère spécial avec des 0 de nouveau.

3voto

Scott Points 3192

Le suivant sera de retour '0' si la chaîne est entièrement composé de zéros:

CASE WHEN SUBSTRING(str_col, PATINDEX('%[^0]%', str_col+'.'), LEN(str_col)) = '' THEN '0' ELSE SUBSTRING(str_col, PATINDEX('%[^0]%', str_col+'.'), LEN(str_col)) END AS str_col

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X