【问题标题】:get the maximum number that extracted from a string using mysql获取使用mysql从字符串中提取的最大数
【发布时间】:2017-11-13 14:45:38
【问题描述】:

我有一个名为 Elements 的表格

id    reference
101   AES/JN/2001
102   AMES/JN/2001
103   AES/JN/2002
104   AES/JN/2003
105   AMES/JN/2002

我想从字符串中获取最大数。如果我的搜索关键字是 AMES/JN,我应该得到 2002。如果我的关键字是 AES/JN,那么输出应该是 2003

我已经尝试了以下代码:

select max(convert(substring_index(reference,'/', -1), unsigned)) as max
        FROM Elements  WHERE reference like 'AES/JN/'

【问题讨论】:

    标签: php mysql string substring


    【解决方案1】:
    SELECT MAX(Z.COUNT),reference FROM
    (
      SELECT reference,CAST(SUBSTRING_INDEX(reference, '/', -1) AS DECIMAL) count 
      FROM Elements where reference like 'AES/JN/%'
    )Z
    

    试试上面的代码。

    希望这会有所帮助。

    【讨论】:

    • 做评论,如果你不赞成某个人..!!
    • 我没有对此投反对票,但谁曾投反对票可能是因为您使用的是子查询,而无需子查询就可以实现所需的结果。
    • @mickmackusa 是的。
    【解决方案2】:

    请检查“LIKE”的工作原理。 你可以使用 % 作为小丑

    只需更改您的查询并添加 % 字符。这是工作

        SELECT
        max(
            CONVERT (
                substring_index(reference, '/', - 1),
                UNSIGNED
            )
        ) AS max
    FROM
        reference
    WHERE
        reference LIKE 'AES/JN/%'
    

    请注意:LIKE 'AES/JN/%'

    【讨论】:

      【解决方案3】:

      请找到以下解决方案。

      查询:

      select id,reference,digits(reference) as num_values from asasas where reference like 'AMES/JN%' order by num_values DESC limit 1
      

      你需要在mysql中创建一个函数

      DELIMITER $$
      
      DROP FUNCTION IF EXISTS `test`.`digits`$$
      
      CREATE FUNCTION `digits`( str CHAR(32) ) RETURNS char(32) CHARSET latin1
      BEGIN
        DECLARE i, len SMALLINT DEFAULT 1;
        DECLARE ret CHAR(32) DEFAULT '';
        DECLARE c CHAR(1);
        IF str IS NULL
        THEN 
          RETURN "";
        END IF;
        SET len = CHAR_LENGTH( str );
        REPEAT
          BEGIN
            SET c = MID( str, i, 1 );
            IF c BETWEEN '0' AND '9' THEN 
              SET ret=CONCAT(ret,c);
            END IF;
            SET i = i + 1;
          END;
        UNTIL i > len END REPEAT;
        RETURN ret;
      END$$
      
      DELIMITER ;
      

      如果它不适合你,请告诉我

      【讨论】:

        【解决方案4】:

        我几乎同意 Shyam 的观点,除了那个非常复杂的函数。

        我推荐这个查询:

        SELECT SUBSTRING_INDEX(reference,'/',-1) as `max`
        FROM `Elements`
        WHERE reference LIKE 'AES/JN/%'
        ORDER BY reference DESC
        LIMIT 1
        

        这将输出以2003 作为max 列中的值的单行。

        我喜欢这种方法的原因是CONVERT() 被省略/不必要。

        我已将我的查询与服务器上的 Xenofexs' 进行了比较,我的查询仅快 .0001 秒——但这仅在 OP 发布的 5 行上运行。随着数据库量的增加,我相信我的查询的性能领先优势将会增加。

        即使你不关心微优化,我认为这个查询更容易阅读/理解,因为它在函数内部没有函数。


        事实上,我相信下一个查询可能会胜过我上面的查询:

        SELECT SUBSTRING_INDEX(reference,'/',-1) as `max`
        FROM `Elements`
        WHERE LOCATE('AES/JN/',reference)
        ORDER BY reference DESC
        LIMIT 1
        

        因为LOCATE() 将检查reference 列中的前导字符,并且目标子字符串不会出现在字符串的后面,所以LOCATE() 的性能已超过LIKE

        补充阅读:
        MySQL LIKE vs LOCATE


        作为记录,这是我使用的表格:

        CREATE TABLE `Elements` (
          `id` int(10) NOT NULL,
          `reference` varchar(100) NOT NULL
        ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
        
        INSERT INTO `Elements` (`id`, `reference`) VALUES
        (101, 'AES/JN/2001'),
        (102, 'AMES/JN/2001'),
        (103, 'AES/JN/2002'),
        (104, 'AES/JN/2003'),
        (105, 'AMES/JN/2002');
        
        ALTER TABLE `Elements`
          ADD PRIMARY KEY (`id`);
        
        ALTER TABLE `Elements`
          MODIFY `id` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=106;
        

        【讨论】:

        • 您应该使用LIKE 解决方案,并在reference 列上添加索引。该索引将帮助LIKE 更快地执行,它也将帮助ORDER BY。 LOCATE() 解决方案不能使用索引,它将强制进行表扫描。使用 EXPLAIN 确认这一点。
        • P.S. Don't use MyISAM。 :-)
        猜你喜欢
        • 1970-01-01
        • 2019-04-11
        • 1970-01-01
        • 2019-01-04
        • 1970-01-01
        • 2015-06-21
        • 1970-01-01
        • 2022-11-14
        • 2014-09-08
        相关资源
        最近更新 更多