You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL REGEXP与LEFT用法解析及旧SQL查询代码重构咨询

一、原代码逻辑与关键字说明

这段代码的作用是对分类表cat的标题字段title做拆分取值,最终生成两个互斥的字段:

  • int_cat:如果标题以连续数字开头,就把开头的连续数字转为整数类型存储
  • int_cat_string:如果标题不以数字开头,就把完整的原标题存在这个字段

涉及的两个关键字/函数作用:

  • REGEXP:MySQL的正则匹配操作符,这里的正则规则里^代表匹配字符串的起始位置,[0-9]代表匹配单个数字字符,堆叠多个[0-9]就是校验字符串开头是否存在对应长度的连续数字。
  • LEFT(str, length):MySQL原生字符串截取函数,作用是从指定字符串的最左端开始,截取前length个字符返回。

原代码的判断逻辑是从最长的4位开头数字开始逐次降级匹配:先判断是不是开头有4个连续数字,是就截前4位;不满足就判断是不是3个,是就截前3位,以此类推直到1位;如果开头完全没有数字,就返回NULL。后续int_cat会把截出来的数字串转为有符号整数,int_cat_string则通过判断前面的匹配结果是否为NULL,决定是存原标题还是存NULL。

二、重构优化方案

原代码最大的问题是完全重复写了两遍相同的CASE匹配逻辑,不仅代码冗长难维护,还会让数据库执行两次完全一样的正则校验,产生不必要的性能开销。可以根据使用的MySQL版本选择对应的优化方案:

方案1:MySQL 8.0及以上版本(推荐)

直接用REGEXP_SUBSTR函数一次性提取开头的所有连续数字,不需要逐层判断长度,代码量减少70%以上,且只需要做一次正则匹配:

CAST(REGEXP_SUBSTR(cat.title, '^[0-9]+') AS SIGNED) AS int_cat,
IF(REGEXP_SUBSTR(cat.title, '^[0-9]+') IS NULL, cat.title, NULL) AS int_cat_string,

这里正则^[0-9]+的含义是匹配字符串开头的1个及以上连续数字,不管长度是1位、4位还是更长,都能一次性提取出来,比原来硬编码判断1-4位数字的逻辑兼容性更好,遇到开头超过4位数字的标题也不会截断出错。

方案2:兼容MySQL 5.x旧版本

如果是MySQL 5.7及更早不支持REGEXP_SUBSTR的版本,可以通过派生表提前计算一次匹配结果,避免重复写CASE逻辑,同时可以把重复的正则写法用量词简化([0-9]{n}代表n个连续数字,和原来写n个[0-9]效果完全一致,可读性更高):

CAST(num_prefix AS SIGNED) AS int_cat,
IF(num_prefix IS NULL, cat.title, NULL) AS int_cat_string
FROM (
    SELECT
        cat.*,
        CASE
            WHEN cat.title REGEXP "^[0-9]{4}" THEN LEFT(cat.title,4)
            WHEN cat.title REGEXP "^[0-9]{3}" THEN LEFT(cat.title,3)
            WHEN cat.title REGEXP "^[0-9]{2}" THEN LEFT(cat.title,2)
            WHEN cat.title REGEXP "^[0-9]" THEN LEFT(cat.title,1)
            ELSE NULL
        END AS num_prefix
    FROM cat
) t

注意:这个写法保留了原代码最多匹配4位开头数字的逻辑,如果业务上允许开头数字超过4位,建议升级MySQL版本采用方案1的写法,避免出现数字截断错误。


内容的提问来源于stack exchange,提问作者Kenneth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 19:27:23