2010-09-16 5 views
3

J'ai commencé par cela, mais est-ce le meilleur moyen d'effectuer la tâche?Analyser une chaîne avant le dernier index d'un caractère dans SQL Server

select 
    reverse(
     substring(reverse(some_field), 
     charindex('-', reverse(some_field)) + 1, 
     len(some_field) - charindex('-', reverse(some_field)))) 
from SomeTable 
  1. Comment SQL Server traiter les appels multiples à reverse(some_field)?
  2. Outre une UDF et itérer la chaîne à la recherche de charindex du « - » et le stockage du dernier indice de celui-ci, est-il plus moyen efficace d'effectuer cette tâche dans T-SQL?

Notez que ce que j'ai fonctionne, je me demande vraiment si c'est la meilleure façon de le faire.

Ci-dessous des exemples de valeurs pour some_field.

s2-st, s1-st, s3-st, s3-sss-zzz, s4-sss-zzzz 

EDIT:

Exemple de sortie pour ce serait ...

s1, s2, s3-sss, s3, s4-sss 

La Erike solution a écrit est réellement obtenir la fin de la chaîne, donc tout après le dernier tiret. Je viens de modifier sa version pour obtenir tout avant d'utiliser une méthode similaire avec la fonction left. Merci pour votre aide.

select left(some_field, abs(charindex('-', reverse(some_field)) - len(some_field))) 
    from (select 's2-st' as some_field 
     union select 's1-st' 
     union select 's3-st' 
     union select 's3-sss-zzz' 
     union select 's4-sss-zzzz') as SomeTable 

Répondre

5

Puis-je suggérer cette simplification de votre expression:

select right(some_field, charindex('-', reverse(some_field)) - 1) 
from SomeTable 

En outre, il n'y a pas de mal, pour autant que je sache, en spécifiant 8000 caractères de longueur avec la fonction de sous-chaîne quand vous voulez que le reste de la chaîne . Tant que ce n'est pas varchar (max), ça marche très bien.

Si c'est quelque chose que vous devez faire tout le temps, encore et encore, que diriez-vous de séparer les données en colonnes séparées et de les stocker de cette façon, ou d'ajouter une colonne calculée avec un index? qui effectuera le calcul une fois au moment de la mise à jour/insertion et pas plus tard.Enfin, je ne sais pas si SQL Server est suffisamment intelligent pour inverser (some_field) une seule fois et l'injecter dans l'autre instance. Quand j'aurai du temps, j'essaierai de comprendre.

Mise à jour

Oops, en quelque sorte je suis arrivé en arrière ce que vous vouliez. Désolé pour ça. La nouvelle expression que vous avez montré peut encore être simplifiée un peu:

select left(some_field, len(some_field) - charindex('-', reverse(some_field))) 
from (
    select 's2-st' 
    union all select 's1-st' 
    union all select 's3-st' 
    union all select 's3-sss-zzz' 
    union all select 's4-sss-zzzz' 
    union all select 's5' 
) X (some_field) 

L'abs() dans votre expression était juste en train d'inverser le signe. Donc, je mets + len - charindex au lieu de + charindex - len et tout va bien maintenant. Il fonctionne même pour des cordes sans tirets.

Une chose à mentionner: vos UNION SELECT s devraient être UNION ALL SELECT parce que sans le ALL, le moteur doit supprimer les doublons comme si vous aviez indiqué SELECT DISTINCT. Prenez simplement l'habitude d'utiliser ALL et vous serez beaucoup mieux lotis. :)

0

Je ne suis pas sûr du point n ° 1, mais je dirais que vous feriez peut-être mieux de le faire dans le code. Y a-t-il une raison pour laquelle vous devez le faire dans la base de données?

Vous rencontrez des problèmes de performance à cause d'un code similaire ou est-ce purement hypothétique?

+0

Cela se fait en SQL parce que c'est vraiment la seule option en raison d'un hack et quelqu'un paresseux (pas moi). On m'a demandé s'il y avait un moyen d'obtenir les valeurs pour eux, alors je leur ai fourni et je les ai mis en garde contre son utilisation. Je me suis toujours interrogé sur l'utilisation de fonctions telles que remplacer ou inverser dans les sélections quand ils sont sur les mêmes champs et comment cela fonctionne. J'ai pensé que c'était un bon exemple de problème que j'ai rencontré pour poser la question. Je suis d'accord que la méthode préférable serait de le faire dans le code client en quelque sorte. –

+0

BTW - j'ai oublié de mentionner Je ne rencontre pas de problèmes de performances, mais souvent j'écris des requêtes qui fonctionnent sur des milliers de lignes et j'utilise des fonctions de chaînes pour renseigner les tables de reporting et curieux comment ça marche. Comme vous le savez, tout ce que je peux faire pour optimiser les performances des requêtes est toujours un plus. –

0

Je ne suis pas sûr non plus comment SQL Server gère les appels multiples à REVERSE et CHARINDEX.

Vous pouvez éliminer le dernier appel à charindex puisque vous voulez prendre tout à la fin de la chaîne:

select 
    reverse(
     substring(reverse(some_field), 
     charindex('-', reverse(some_field)) + 1, 
     len(some_field))) 
from SomeTable 

Bien que je recommande contre, vous pouvez également remplacer l'appel de fonction LEN avec la taille de la colonne:

select 
    reverse(
     substring(reverse(some_field), 
     charindex('-', reverse(some_field)) + 1, 
     1024)) 
from SomeTable 

Je suis curieux de savoir quelle serait l'ampleur de ces changements.

0
  1. Les 3 inverses internes sont discrets les uns des autres. L'inversion externe inverse tout ce qui est déjà inversé par les internes.

  2. L'approche d'ErikE est la meilleure solution en tant que solution TSQL pure. Vous n'avez pas besoin LEN

Questions connexes