在MySQL中查找给定子字符串的最后一个索引

89

我们可以使用MySQL的INSTR()函数来查找给定子字符串第一次出现的索引,如下所示。

SELECT instr('Have_a_good_day', '_') AS index_position

它将显示5,这是指定子字符串的第一个出现,本例中为下划线_

我需要获取给定字符(或子字符串)的最后一次出现,类似于Java String类的lastIndexOf(String str)方法,但我找不到MySQL中的任何内置函数。

在MySQL中是否有任何内置功能可以实现这一点?


如果有人有解决方案,请将其添加为答案。 - Tiny
7个回答

180

@Marc B 已经接近正确。在MySQL中,以下语句返回12:

SELECT CHAR_LENGTH("Have_a_good_day") - LOCATE('_', REVERSE("Have_a_good_day"))+1;

为了预期可能使用的值,以下语句从最后一个下划线(即_)之前的字符串中提取左侧部分:

SELECT LEFT("first_middle_last", CHAR_LENGTH("first_middle_last") - LOCATE('_', REVERSE("first_middle_last")));

结果是"first_middle"。 如果你想要包含分隔符,请使用:
SELECT LEFT("first_middle_last", CHAR_LENGTH("first_middle_last") - LOCATE('_', REVERSE("first_middle_last"))+1);

希望LOCATE函数可以增加一个选项,从右侧开始搜索。

如果你想要在最后一个空格后获取字符串的右侧部分,更好的解决方法是:

SELECT SUBSTRING_INDEX("first_middle_last", '_', -1);

这会返回“last”。

@Tiny,我相信你现在可能已经想出了答案。我也遇到了同样的问题,想要发布一个解决方案。 - curt
当然,我的解决方案是你答案中的第一个。感谢你的回答。 - Tiny
4
SUBSTRING_INDEX非常有用!在PHP中是否有类似的东西? - mikewasmike
1
在 PHP 中,使用 explode 函数;end(explode(',', $string)) 可以获取 $string 中最后一个逗号后面的所有内容。 - Brilliand
3
请记住,LENGTH() 函数返回的是字节长度。如果您在 UTF-8 列上使用这些函数,则结果可能会出错,因为 UTF-8 字符可以有 1 到 3 个字节。为了安全起见,在多种不同字符集上使用这些函数时,请改用 CHAR_LENGTH() 函数。 - Eduardo
显示剩余2条评论

26

我认为你可以这样使用substring_index:

select substring_index(string, delimiter,-1)

-1将从字符串结尾开始。


当然我知道可以,但它显示的是子字符串本身(在提取完成后),而不是该子字符串的索引位置。在这种情况下,它会显示day,但我需要显示指定子字符串的索引12 - Tiny
你的文本有多长?你能反转它,然后使用instr或locate函数吗?我知道这不是最理想的方法,但它可以工作。 - rizalp1
无论如何,我都不能考虑反转字符串,因为我需要根据找到的最后一个索引从字符串中提取其他文本。 - Tiny
我需要获取字符串中某个字符最后一次出现的索引之前和之后的所有内容,这个方法帮助了我实现这个功能。 - chiliNUT
太棒了!这在mysql 5.7上非常好用!!!谢谢 - Fernando Torres

24

如果您不想使用REVERSE函数,则可以使用以下方法:

LEFT
(
   'Have_a_good_day', 
   LENGTH('Have_a_good_day') - LENGTH(SUBSTRING_INDEX('Have_a_good_day','_',-1))-1
)

这正是我所拥有的,我认为它比使用“reverse”更好。 - Fr0zenFyr
5
这与已接受的答案不同,因为没有定界符的字符串(例如Have)将变成空字符串,而不是Have - l33t

3

反转/索引的组合?

SELECT LENGTH(string) - SUBSTRING_INDEX(REVERSE(string), delimiter) + 1

将其分解,考虑到您的Have_a_good_day:
REVERSE('Have_a_good_day') -> yad_doog_a_evaH
SUBSTRING_INDEX('yad_doog_a_evah', '_') -> 4
LENGTH('Have_a_good_day') -> 15
15 - 4 + 1 -> 12

Have_a_good_day
123456789012345
           ^

SUBSTRING_INDEX('yad_doog_a_evah', '_') 会出现错误 在调用本地函数'SUBSTRING_INDEX'时参数计数不正确。它需要一个第三个参数,例如 SUBSTRING_INDEX('yad_doog_a_evah', '_', 1),这将产生子字符串 yad 而不是在此情况下的第一个 _ 的索引,即 4。感谢您的回复。 - Tiny
你有解决方案吗?我可以做,但是方法很丑陋,令人讨厌且可避免。谢谢。 - Tiny

3
我发现这是一个很好的技巧来完成它:
SELECT LOCATE(SUBSTRING_INDEX('Have_a_good_day', '_', -1),'Have_a_good_day')-1 AS indexpos;

这将返回最后一次出现的索引(=12)。基本上,您需要搜索分隔符后面的字符串右侧部分,并在整个字符串中搜索此子字符串的位置,以获取位置:)
如果您想获得该子字符串左侧的子字符串,可以使用以下方法:
SELECT
  SUBSTRING('Have_a_good_day', 1, 
     LOCATE(SUBSTRING_INDEX('Have_a_good_day', '_', -1),'Have_a_good_day')-1) 
  AS sub;

0

虽然上述代码可以成功地查找单个字符,但当我尝试使用它们来查找子字符串的最后一次出现时,它们失败了。因此,我建议使用以下代码来完成此任务:

SELECT LENGTH("my father is my father")
        - LOCATE('father', REVERSE("my father is my father"))-(LENGTH('father')-1)

这应该返回17


+1 是指出被接受的答案和其他答案只适用于单个字符,但您的答案需要修改(您在搜索输入中最后一个字符串的模式时运气好。尝试使用“my”或在最后一个“father”之后添加文本,它将无法正常工作)。请尝试此代码: SELECT LENGTH("my father is my father") - LOCATE(REVERSE('my'), REVERSE("my father is my father"))-(LENGTH('my')-2) - tcashin

0

从双重选择(length("Have_a_good_day") - instr(reverse("Have_a_good_day"),'_')));


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接