Trouver l'indice de la dernière occurrence d'une sous-chaîne à l'aide de T-SQL
Est-il un moyen simple de trouver l'indice de la dernière occurrence d'une chaîne à l'aide de SQL? Je suis à l'aide de SQL Server 2000 à l'instant. En gros, j'ai besoin de la fonctionnalité de la .NET System.String.LastIndexOf
méthode fournit. Un peu googler a révélé ce - Fonction Pour Récupérer Le Dernier Indice - mais qui ne fonctionne pas si vous passez dans un "texte" expression de la colonne. D'autres solutions trouvées ailleurs le travail, aussi longtemps que le texte que vous recherchez est de 1 caractère.
Je vais probablement avoir à faire cuire une fonction. Si je le fais, je vais le poster ici afin de vous des gens peuvent la regarder et peut-être faire usage de.
Vous devez vous connecter pour publier un commentaire.
Vous êtes limité à petite liste de fonctions pour le type de données texte.
Tout ce que je peux suggérer, c'est de commencer avec
PATINDEX
, mais travailler à rebours à partir deDATALENGTH-1, DATALENGTH-2, DATALENGTH-3
etc jusqu'à ce que vous obtenez un résultat ou à la fin jusqu'à zéro (DATALENGTH-DATALENGTH)C'est vraiment quelque chose que
SQL Server 2000
simplement ne peut pas gérer.Modifier d'autres réponses : INVERSE n'est pas sur la liste des fonctions qui peuvent être utilisées avec les données de texte dans SQL Server 2000
DATALENGTH
renvoie le nombre d'octets non caractères. Par conséquent,DATALENGTH
renvoie 2 x le nombre de caractères dans une chaîne de caractères pourNVARCHAR
cordes.LEN
, cependant, renvoie le nombre de caractères, moins tous les espaces. Je n'ai jamais utiliserDATALENGTH
de personnages pour le calcul de la longueur à moins de fuite espace est important et je sais pour sûr que mes types de données sont cohérentes, qu'elles soientVARCHAR
ouNVARCHAR
De façon simple? Non, mais j'ai utilisé l'inverse. Littéralement.
En avant des routines, pour trouver cours de la dernière occurence d'une chaîne de caractères, j'ai utilisé le REVERSE() de la fonction, suivi CHARINDEX, suivi de nouveau par l'INVERSE de restaurer l'ordre original. Par exemple:
montre comment extraire la base de données des noms de fichiers à partir de leur "physique" de noms, n'importe comment profondément imbriqués dans des sous-dossiers. Cela ne rechercher qu'un seul caractère (la barre oblique inverse), mais vous pouvez construire sur cette pour de plus longues chaînes de recherche.
Le seul inconvénient est que je ne sais pas comment cela fonctionne sur les types de données TEXTE. J'ai été sur SQL 2005 depuis quelques années maintenant, et je ne suis plus familier avec l'utilisation du TEXTE -- mais il me semble que vous pourriez utiliser à GAUCHE et à DROITE sur elle?
Philip
La façon la plus simple est....
[expr]
est de plus de 1 symbole, vous devez inverser trop!Si vous utilisez sql server 2005 ou au-dessus, à l'aide de
REVERSE
fonction de beaucoup de temps qui est préjudiciable à la performance, code ci-dessous est plus efficace.Vieux mais toujours valide question, donc voici ce que j'ai créé basée sur les informations fournies par d'autres ici.
Cela a fonctionné très bien pour moi.
ont mieux fonctionné pour moi
Hmm, je sais que c'est un vieux thread, mais un tableau de pointage pourrait le faire dans SQL2000 (ou toute autre base de données):
Un tableau de pointage est juste un tableau de l'incrémentation des numéros.
La
substring(@str, _Tally.n, 1) = @delim
obtient la position de chaque séparateur, puis vous venez d'obtenir le maximum de la position de cet ensemble.Tally tables sont impressionnantes. Si vous n'avez pas utilisé avant, il y a un bon article sur SQL Server Centrale (Gratuit reg, ou tout simplement utiliser de Bug Moi de ne Pas (http://www.bugmenot.com/view/sqlservercentral.com)).
*EDIT: Supprimé
n <= LEN(TEXT_FIELD)
, que vous ne pouvez pas utiliser LEN() sur le type de TEXTE. Tant que lesubstring(...) = @delim
demeure cependant le résultat est toujours correcte.Inverser la fois de votre chaîne et de vos sous-chaîne, puis de rechercher la première occurrence.
Je réalise que c'est un vieux de plusieurs années question, mais...
Sur
Access 2010
, vous pouvez utiliserInStrRev()
pour ce faire. Espérons que cette aide.Je sais qu'il sera inefficace, mais avez-vous considéré le casting du
text
champ devarchar
de sorte que vous pouvez utiliser la solution fournie par le site vous avez trouvé? Je sais que cette solution serait de créer des questions que vous pourriez potentiellement tronquer l'enregistrement si la longueur de latext
champ débordait de la longueur de votrevarchar
(pour ne pas mentionner il ne serait pas très performant).Vos données sont à l'intérieur d'un
text
champ (et que vous utilisez SQL Server 2000) vos options sont limitées.Si vous souhaitez obtenir l'index de la dernière de l'espace dans une chaîne de mots, vous pouvez utiliser cette expression
DROIT de(nom, prénom, (CHARINDEX(' ',l'INVERSE de(nom),0)) pour revenir le dernier mot dans la chaîne. Ceci est utile si vous souhaitez analyser le prénom d'un nom complet qui comprend initiales, par la première et /ou deuxième prénom.
@indexOf = <whatever characters you are searching for in your string>
@LastIndexOf = LEN([MyField]) - CHARINDEX(@indexOf, REVERSE([MyField]))
Ne l'ai pas testé, il peut être désactivé par un car de l'index de zéro, mais travaille en
SUBSTRING
fonction lors de la coupe hors de@indexOf
caractères à la fin de votre chaîne deSUBSTRING([MyField], 0, @LastIndexOf)
Certains des autres réponses retourner une chaîne réelle alors que je n'avais plus besoin de savoir l'indice réel de type int. Et les réponses que faire, qui semblent à compliquer les choses. À l'aide de certaines autres réponses comme source d'inspiration, je n'ai la suite...
Tout d'abord, j'ai créé une fonction:
Ensuite, dans votre requête, vous pouvez simplement faire ceci:
Ci-dessus doit retourner 23 (le dernier index de ':')
Espérons que cela fait un peu plus facile pour quelqu'un!
Cette réponse utilise MS SQL Server 2008 (je n'ai pas accès à MS SQL Server 2000), mais la façon dont je le vois en fonction de l'OP sont 3 situations à prendre en considération. De ce que j'ai essayé pas de réponse ici couvre tous les 3 d'entre eux:
caractère) dans une chaîne donnée.
0
La fonction, je suis venu avec prend 2 paramètres:
@String NVARCHAR(MAX)
: La chaîne à rechercher@FindString NVARCHAR(MAX)
: Soit un seul caractère ou une sous-chaîne pour obtenir la dernièreindice de
@String
Elle renvoie un
INT
qui est l'indice positif de@FindString
dans@String
ou0
sens que@FindString
n'est pas dans@String
Voici une explication de ce que la fonction n':
@ReturnVal
à0
indiquant que@FindString
n'est pas dans@String
@FindString
dans@String
en utilisantCHARINDEX()
@FindString
dans@String
est0
,@ReturnVal
est à gauche que0
@FindString
dans@String
est> 0
,@FindString
est dans@String
doncil calcule le dernier indice de
@FindString
dans@String
en utilisantREVERSE()
@ReturnVal
qui est un nombre positif qui est le dernier indice de@FindString
dans@String
ou0
indiquant que@FindString
n'est pas dans@String
Voici la fonction créer un script (copiez et collez prêt):
Ici est un peu ce qu'idéalement les tests de la fonction:
J'ai seulement l'exécuter sur MS SQL Server 2008, car je n'ai pas accès à toute les autres version mais de ce que j'ai regardé dans ce qui devrait être bon pour 2008+ au moins.
Profiter.
J'ai besoin de trouver la nième dernière position d'une barre oblique inverse dans un chemin d'accès au dossier.
Voici ma solution.
Voici mon cas de test qui passent
Pour obtenir la partie avant de la dernière occurence de la délimiteur (fonctionne uniquement pour les
NVARCHAR
en raison deDATALENGTH
utilisation):Cette réponse est conforme aux exigences de l'OP. plus précisément, il permet à l'aiguille pour être plus qu'un personnage simple et il ne génère pas une erreur lors de l'aiguille n'est pas trouvé dans la botte de foin. Il me semblait que la plupart (tous?) les autres réponses ne gère pas ces cas limites. Au-delà que j'ai ajouté la "Position de Départ" argument fourni par le natif de MS SQL server CharIndex fonction. J'ai essayé de correspondre exactement à la spécification pour CharIndex, sauf à traiter de droite à gauche au lieu de gauche à droite. par exemple, je renvoie null si l'aiguille ou la botte de foin est nul et je retourne zéro si needle n'est pas trouvé dans la botte de foin. Une chose que je ne pouvais pas contourner, c'est qu'avec le construit en fonction de la troisième paramètre est facultatif. Avec SQL Server fonctions définies par l'utilisateur, tous les paramètres doivent être fournis dans l'appel, sauf si la fonction est appelée à l'aide de "EXEC" . Tandis que le troisième paramètre doit être inclus dans la liste des paramètres, vous pouvez fournir le mot-clé "par défaut" comme un espace réservé pour elle sans avoir à donner une valeur (voir les exemples ci-dessous). Puisqu'il est plus facile d'enlever la troisième paramètre de cette fonction, si elle n'est pas désirée que ce serait pour ajouter, au besoin, j'ai compris ici comme un point de départ.
Je suis tombé sur ce fil, alors que la recherche d'une solution à mon problème semblable qui avait exactement la même exigence, mais il était un autre type de base de données qui a été également dépourvues de la
REVERSE
fonction.Dans mon cas c'était pour un OpenEdge (Progrès) base de données, qui a une syntaxe légèrement différente. Ce qui fait que la
INSTR
fonction disponible pour moi que la plupart Oracle tapé offre de bases de données.Alors je suis venu avec le code suivant:
Cependant, pour ma situation spécifique (la OpenEdge (Progrès) base de données), cela n'a pas abouti dans le comportement souhaité, car en remplaçant le personnage avec un vide char a donné la même longueur que la chaîne d'origine. Cela ne fait pas beaucoup de sens pour moi, mais j'ai été en mesure de contourner le problème avec le code ci-dessous:
Maintenant, je comprends que ce code ne suffit pas à résoudre le problème pour T-SQL car il n'y a pas d'alternative à la
INSTR
fonction qui offre laOccurence
propriété.Juste pour être complet, je vais ajouter le code nécessaire pour créer cette fonction scalaire de sorte qu'il peut être utilisé de la même façon comme je l'ai fait dans les exemples ci-dessus.
Pour éviter l'évidence, quand la
REVERSE
fonction est disponible, vous n'avez pas besoin de créer cette fonction scalaire et vous pouvez juste obtenir le résultat requis comme ceci:Ce code fonctionne même si la sous-chaîne contient plus de 1 caractère.