【问题标题】:Selecting first 4 numbers from a string MySQL从字符串 MySQL 中选择前 4 个数字
【发布时间】:2017-09-29 00:57:44
【问题描述】:

如果我有这样的字符串:

CC123484556
CC492014512
BUXT122256690

如何在 MySQL 中操作这样的代码来提取前 4 个数字值?其他行中的数字前有各种 # 个字母,但最重要的是出现的前 4 个数字。

SELECT LEFT(alloy , 4) FROM tbl 

所以想要的结果是:

1234
4920
1222

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    又慢又丑:

    SELECT col,
           SUBSTRING(tab.col, MIN(LOCATE(four_digits, tab.col,1)), 4) + 0 AS result
    FROM  (SELECT 'CC123484556' AS col UNION ALL
           SELECT 'CC492014512' UNION ALL
           SELECT 'BUXT122256690' UNION ALL
           SELECT 'abced') tab
    CROSS JOIN (
       SELECT  CONCAT(d1.z, d2.z, d3.z, d4.z) AS four_digits
       FROM (SELECT '1' AS z UNION SELECT '2' UNION SELECT '3' UNION
                SELECT '4' UNION SELECT '5' UNION SELECT '6' UNION
                SELECT '7' UNION SELECT '8' UNION SELECT '9' UNION SELECT '0') d1
      CROSS JOIN (SELECT '1' AS z UNION SELECT '2' UNION SELECT '3' UNION
                SELECT '4' UNION SELECT '5' UNION SELECT '6' UNION
                SELECT '7' UNION SELECT '8' UNION SELECT '9' UNION SELECT '0') d2
      CROSS JOIN (SELECT '1' AS z UNION SELECT '2' UNION SELECT '3' UNION
                SELECT '4' UNION SELECT '5' UNION SELECT '6' UNION
                SELECT '7' UNION SELECT '8' UNION SELECT '9' UNION SELECT '0') d3
      CROSS JOIN (SELECT '1' AS z UNION SELECT '2' UNION SELECT '3' UNION
                SELECT '4' UNION SELECT '5' UNION SELECT '6' UNION
                SELECT '7' UNION SELECT '8' UNION SELECT '9' UNION SELECT '0') d4
     ) sub
    WHERE LOCATE(four_digits, tab.col,1) > 0
    GROUP BY col;
    

    Rextester Demo

    生成所有 4 位数字组合,在字符串中定位它们并获取索引最低的子字符串。

    编辑:

    更快一点的方法:

    SELECT col, SUBSTRING(col, MIN(i), 4) + 0 AS r
    FROM (
        SELECT col, SUBSTRING(tab.col, i , 4) + 0 AS result, i
        FROM tab
        CROSS JOIN (
           SELECT  CONCAT(d1.z, d2.z)+1 AS i
           FROM (SELECT '1' AS z UNION SELECT '2' UNION SELECT '3' UNION
                    SELECT '4' UNION SELECT '5' UNION SELECT '6' UNION
                    SELECT '7' UNION SELECT '8' UNION SELECT '9' UNION SELECT '0') d1
          CROSS JOIN (SELECT '1' AS z UNION SELECT '2' UNION SELECT '3' UNION
                    SELECT '4' UNION SELECT '5' UNION SELECT '6' UNION
                    SELECT '7' UNION SELECT '8' UNION SELECT '9' UNION SELECT '0') d2
         ) sub
         WHERE  i <= LENGTH(tab.col)-1
    ) sub
    WHERE result <> 0
    GROUP BY col;
    

    Rextester Demo2

    从头开始获取4个字符的子串,隐式转换为数字,获取i最低的数字。

    【讨论】:

    • 可能最简单的方法是 REPLACE 所有带空格的非数字字符并在结果上使用 LEFT(..., 4) + 0。不幸的是 MySQL 不支持 REGEX_REPLACE。
    【解决方案2】:

    使用locate()least()substr()

    SQLFiddle Demo

    select col,SUBSTR(col,LEAST(
        if (Locate(0,col) >0,Locate(0,col),999),
        if (Locate(1,col) >0,Locate(1,col),999),
        if (Locate(2,col) >0,Locate(2,col),999),
        if (Locate(3,col) >0,Locate(3,col),999),
        if (Locate(4,col) >0,Locate(4,col),999),
        if (Locate(5,col) >0,Locate(5,col),999),
        if (Locate(6,col) >0,Locate(6,col),999),
        if (Locate(7,col) >0,Locate(7,col),999),
        if (Locate(8,col) >0,Locate(8,col),999),
        if (Locate(9,col) >0,Locate(9,col),999)
      ),4) as result from test;
    

    测试结果:

    mysql> create table test ( col varchar(15));
    Query OK, 0 rows affected (0.70 sec)
    
    mysql> insert into test (col) values 
        -> ('CC123484556'),
        -> ('CC492014512'),
        -> ('BUXT122256690');
    Query OK, 3 rows affected (0.13 sec)
    Records: 3  Duplicates: 0  Warnings: 0
    

    输出:

    mysql> select * from test;
    +---------------+
    | col           |
    +---------------+
    | CC123484556   |
    | CC492014512   |
    | BUXT122256690 |
    +---------------+
    3 rows in set (0.00 sec)
    
    mysql> select col,SUBSTR(col,LEAST(
        ->     if (Locate(0,col) >0,Locate(0,col),999),
        ->     if (Locate(1,col) >0,Locate(1,col),999),
        ->     if (Locate(2,col) >0,Locate(2,col),999),
        ->     if (Locate(3,col) >0,Locate(3,col),999),
        ->     if (Locate(4,col) >0,Locate(4,col),999),
        ->     if (Locate(5,col) >0,Locate(5,col),999),
        ->     if (Locate(6,col) >0,Locate(6,col),999),
        ->     if (Locate(7,col) >0,Locate(7,col),999),
        ->     if (Locate(8,col) >0,Locate(8,col),999),
        ->     if (Locate(9,col) >0,Locate(9,col),999)
        ->   ),4) as result from test;
    +---------------+--------+
    | col           | result |
    +---------------+--------+
    | CC123484556   | 1234   |
    | CC492014512   | 4920   |
    | BUXT122256690 | 1222   |
    +---------------+--------+
    3 rows in set (0.00 sec)
    

    【讨论】:

    • 有趣的方法:)
    • @lad2025 谢谢,有时会想到,但需要时却没有:)
    猜你喜欢
    • 2019-01-02
    • 2014-11-25
    • 2020-07-20
    • 2023-01-04
    • 2014-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多