MySQL正则表达式在处理重复字符时返回错误的结果

MySQL regexp returns wrong result when working with repeated character

提问人:NotX 提问时间:11/15/2023 最后编辑:NotX 更新时间:11/15/2023 访问量:63

问:

在MySQL 5.7中,我有以下查询:

SELECT `slug` FROM `unittest`.`test_item`
WHERE `slug` REGEXP '^some-slug[0-9]*$'
ORDER BY `slug` DESC LIMIT 1;

这对于带有蛞蝓的物品来说效果很好,但是一旦我有像这样的蛞蝓,就找不到那个了。相反,结果一直都是。 我在 regex101.com 设置了一个示例,它似乎有效。some-slug1some-slug9some-slug10some-slug9

关于MySQL,我在这里错过了什么?

MySQL 正则表达式

评论

0赞 Mureinik 11/15/2023
当我测试它时,它似乎工作得很好:dbfiddle.uk/aHuXWht9 .你确定那里没有其他事情发生吗?
1赞 Barmar 11/15/2023
你有,所以它只返回第一个结果。如果你返回所有结果,你会看到。LIMIT 1some-slug10
1赞 Barmar 11/15/2023
由于它是一个字符串,所以它正在执行字典排序,而不是数字排序,所以9 > 10
1赞 Barmar 11/15/2023
@user1191247 这是行不通的,因为数字不在 的开头。slug
2赞 user1191247 11/15/2023
@Barmar谢谢。我傻了。能ORDER BY SUBSTRING(`slug`, 10) + 0 DESC

答:

1赞 Luuk 11/15/2023 #1

另一种选择:

SELECT 
  `slug`,
  REGEXP_REPLACE(`slug`,'[a-z]','')
FROM `test_item`
WHERE `slug` REGEXP '^some-slug[0-9]*$'
ORDER BY CAST(REGEXP_REPLACE(`slug`,'[a-z]','') as SIGNED)

请参见:DBFIDDLE

编辑:作为奖励(只是为了学习)

为什么这也是正确的顺序?

SELECT 
  `slug`,
  REGEXP_REPLACE(`slug`,'[a-z]','')
FROM `test_item`
WHERE `slug` REGEXP '^some-slug[0-9]*$'
ORDER BY CAST(REGEXP_REPLACE(`slug`,'[a-z]','') as UNSIGNED)

请参见:DBFIDDLE

提示:只需将 slug 添加到您的选择中,您就会明白原因。CAST(REGEXP_REPLACE(,'[a-z]','') as UNSIGNED)

2赞 user1191247 11/15/2023 #2

如果将查询更改为:

SELECT `slug`
FROM `unittest`.`test_item`
WHERE `slug` REGEXP '^some-slug[0-9]*$'
ORDER BY SUBSTRING(`slug`, 10) + 0 DESC
LIMIT 1;

SUBSTRING('slug', 10) ( 是第一位数字的位置) 将数字组件作为字符串返回,然后导致隐式转换为数值(根据 Workbench 为 DOUBLE)。10+0

您还可以:

ORDER BY CAST(SUBSTRING(`slug`, 10) AS UNSIGNED) DESC

显式 CAST() 将数值分量转换为 .UNSIGNED BIGINT

这是一个 db<>小提琴

P.S. 有趣的是,对于这个简单的案例,比 .在这种情况下,这不太可能很重要,但作为一般规则值得牢记。如果你有一个非常简单的场景,可以很容易地用简单的字符串函数来解决,那么它们比调用正则表达式要快得多。SUBSTRING()REGEXP_REPLACE()

评论

1赞 NotX 11/15/2023
再次感谢您的帮助!你可能会在那里添加一个解释。(只是为了完整起见,我理解它是 9 个字符单词之后的位置。10"some-slug"
1赞 user1191247 11/15/2023
添加了简要说明;-)