Есть ли простой способ найти индекс последнего вхождения строки с помощью SQL? Я использую SQL Server 2000 прямо сейчас. Мне в основном нужна функциональность, которую System.String.LastIndexOf
предоставляет метод .NET . Небольшой поиск в Google показал это - функция для получения последнего индекса - но это не работает, если вы передаете "текстовое" выражение столбца. Другие решения, найденные в другом месте, работают только до тех пор, пока текст, который вы ищете, составляет 1 символ.
Мне, наверное, придется приготовить еду. Если я это сделаю, я опубликую его здесь, чтобы вы, ребята, могли его посмотреть и, возможно, использовать.
DATALENGTH
возвращает количество байтов, а не символов. Следовательно,DATALENGTH
возвращает удвоенное количество символов в строке дляNVARCHAR
строк.LEN
однако возвращает количество символов за вычетом любых конечных пробелов . Я никогда не используюDATALENGTH
для вычисления длины символа, если конечный пробел не является значительным, и я точно знаю, что мои типы данных согласованы, независимо от того, являются ли ониVARCHAR
илиNVARCHAR
Прямолинейный путь? Нет, но я использовал обратное. Буквально.
В предыдущих подпрограммах, чтобы найти последнее вхождение данной строки, я использовал функцию REVERSE (), затем CHARINDEX, а затем снова REVERSE, чтобы восстановить исходный порядок. Например:
показывает, как извлечь фактические имена файлов базы данных из их «физических имен», независимо от того, насколько глубоко они вложены во вложенные папки. При этом выполняется поиск только одного символа (обратная косая черта), но вы можете использовать это для более длинных строк поиска.
Единственный недостаток в том, что я не знаю, насколько хорошо это будет работать с типами данных TEXT. Я использую SQL 2005 уже несколько лет и больше не знаком с работой с ТЕКСТОМ - но я, кажется, припоминаю, что вы могли использовать на нем ВЛЕВО и ВПРАВО?
Филипп
источник
Самый простой способ ...
источник
[expr]
длиннее 1 символа, вам тоже нужно перевернуть его!Если вы используете Sqlserver 2005 или более поздней версии,
REVERSE
многократное использование функции снижает производительность, приведенный ниже код более эффективен.источник
источник
Старый, но все еще актуальный вопрос, вот что я создал на основе информации, предоставленной другими здесь.
источник
У меня это сработало очень хорошо.
источник
работал лучше для меня
источник
Хм, я знаю, что это старый поток, но таблица подсчета может сделать это в SQL2000 (или любой другой базе данных):
Таблица подсчета - это просто таблица возрастающих чисел.
substring(@str, _Tally.n, 1) = @delim
Получает положение каждого разделителя, то вы просто получить позицию максимума в этом наборе.Таблицы подсчета потрясающие. Если вы не использовали их раньше, есть хорошая статья на SQL Server Central (Бесплатная регистрация или просто используйте Bug Me Not ( http://www.bugmenot.com/view/sqlservercentral.com )).
* EDIT: удалено
n <= LEN(TEXT_FIELD)
, так как вы не можете использовать LEN () для типа TEXT. Покаsubstring(...) = @delim
остается хоть результат все равно правильный.источник
Поменяйте местами вашу строку и вашу подстроку, затем найдите первое вхождение.
источник
Некоторые другие ответы возвращают фактическую строку, тогда как мне нужно было больше знать фактический индекс int. И ответы, которые делают это, кажется, слишком усложняют ситуацию. Вдохновляясь некоторыми другими ответами, я сделал следующее ...
Сначала я создал функцию:
Затем в своем запросе вы можете просто сделать это:
Вышеупомянутое должно вернуть 23 (последний индекс ':')
Надеюсь, это кому-то помогло!
источник
Я понимаю, что этому вопросу несколько лет, но ...
На
Access 2010
, вы можете использовать ,InStrRev()
чтобы сделать это. Надеюсь это поможет.источник
В этом ответе используется MS SQL Server 2008 (у меня нет доступа к MS SQL Server 2000), но я вижу это в соответствии с OP, это 3 ситуации, которые следует учитывать. Из того, что я пробовал, ответ здесь не охватывает всех трех из них:
0
Функция, которую я придумал, принимает 2 параметра:
@String NVARCHAR(MAX)
: Строка для поиска@FindString NVARCHAR(MAX)
: Либо одиночный символ, либо подстрока, для получения последнего индекса в@String
Она возвращает
INT
что либо положительный индекс@FindString
в@String
или0
что означает , что@FindString
не в@String
Вот объяснение того, что делает функция:
@ReturnVal
на0
что указывает@FindString
не в@String
@FindString
in@String
с помощьюCHARINDEX()
@FindString
in@String
равен0
,@ReturnVal
остается как0
@FindString
in@String
равен> 0
,@FindString
is in,@String
поэтому последний индекс@FindString
in вычисляется@String
с помощьюREVERSE()
@ReturnVal
либо положительное число, которое является последним индексом@FindString
в,@String
либо0
указывает, что@FindString
не входит@String
Вот сценарий создания функции (готово для копирования и вставки):
Вот небольшой фрагмент, который удобно проверяет функцию:
Я запускал это только на MS SQL Server 2008, потому что у меня нет доступа к какой-либо другой версии, но из того, что я изучил, это должно быть хорошо, по крайней мере, для 2008+.
Наслаждаться.
источник
Я знаю, что это будет неэффективно, но рассматривали ли вы возможность преобразования
text
поля,varchar
чтобы можно было использовать решение, предоставленное веб-сайтом, который вы нашли? Я знаю, что это решение вызовет проблемы, поскольку вы потенциально можете обрезать запись, если длина вtext
поле превышает длину вашегоvarchar
(не говоря уже о том, что это будет не очень производительно).Поскольку ваши данные находятся внутри
text
поля (и вы используете SQL Server 2000), ваши возможности ограничены.источник
Если вы хотите получить индекс последнего пробела в строке слов, вы можете использовать это выражение RIGHT (name, (CHARINDEX ('', REVERSE (name), 0)), чтобы вернуть последнее слово в строке. полезен, если вы хотите разобрать фамилию из полного имени, которое включает инициалы для имени и / или отчества.
источник
@indexOf = <whatever characters you are searching for in your string>
@LastIndexOf = LEN([MyField]) - CHARINDEX(@indexOf, REVERSE([MyField]))
Не тестировал, он может быть отключен на единицу из-за нулевого индекса, но работает в
SUBSTRING
функции при отключении от@indexOf
символов до конца вашей строкиSUBSTRING([MyField], 0, @LastIndexOf)
источник
Этот код работает, даже если подстрока содержит более 1 символа.
источник
Мне нужно было найти n-ю последнюю позицию обратной косой черты в пути к папке. Вот мое решение.
Вот мои тестовые примеры, которые проходят
источник
Для того, чтобы получить часть до последнего совпадения разделителем (работает только
NVARCHAR
за счетDATALENGTH
использования):источник
Этот ответ соответствует требованиям ОП. в частности, он позволяет игле быть более чем одним символом и не генерирует ошибку, если игла не найдена в стоге сена. Мне казалось, что большинство (все?) Других ответов не обрабатывали эти крайние случаи. Кроме того, я добавил аргумент «Начальная позиция», предоставляемый встроенной функцией CharIndex сервера MS SQL. Я попытался точно отразить спецификацию CharIndex, за исключением обработки справа налево, а не слева направо. например, я возвращаю ноль, если игла или стог сена равны нулю, и я возвращаю ноль, если игла не найдена в стоге сена. Одна вещь, которую я не мог обойти, - это то, что со встроенной функцией третий параметр является необязательным. В функциях, определяемых пользователем SQL Server, в вызове должны быть указаны все параметры, кроме случаев, когда функция вызывается с использованием «EXEC». , Хотя третий параметр должен быть включен в список параметров, вы можете указать ключевое слово «default» в качестве заполнителя для него, не задавая ему значение (см. Примеры ниже). Так как при нежелании третий параметр легче удалить из этой функции, чем добавить его при необходимости, я включил его здесь в качестве отправной точки.
источник
Я наткнулся на эту ветку, когда искал решение моей аналогичной проблемы, которая имела те же требования, но была для другого типа базы данных, в которой также не хватало
REVERSE
функции.В моем случае это было для базы данных OpenEdge (Progress) , которая имеет немного другой синтаксис. Это сделало
INSTR
доступной для меня функцию, которую предлагает большинство типизированных баз данных Oracle. .Итак, я придумал следующий код:
Однако для моей конкретной ситуации (являющейся базой данных OpenEdge (Progress) ) это не привело к желаемому поведению, поскольку замена символа пустым символом дала ту же длину, что и исходная строка. Для меня это не имеет особого смысла, но я смог обойти проблему с помощью следующего кода:
Теперь я понимаю, что этот код не решит проблему для T-SQL, потому что нет альтернативы
INSTR
функции, которая предлагаетOccurence
свойство.Чтобы быть внимательным, я добавлю код, необходимый для создания этой скалярной функции, чтобы ее можно было использовать так же, как и в приведенных выше примерах.
Чтобы избежать очевидного, когда
REVERSE
функция доступна, вам не нужно создавать эту скалярную функцию, и вы можете просто получить требуемый результат следующим образом:источник
обрабатывает поиск чего-либо длиной более 1 символа. не стесняйтесь увеличивать размеры parm, если хотите.
не мог сопротивляться публикации
и тесты
источник