Mysql替换使用正则表达式

时间:2016-03-09 15:45:40

标签: mysql regex string

我有类似以下的查询

SELECT FIELDATA FROM DATASET WHERE CATID = 2;

输出

21@Marketing;76@Sales

如果数据库没有存储多个值,输出也可以是以下内容。

21@Marketing

我尝试了以下

SELECT SUBSTRING_INDEX(FIELDATA, '@', -1) AS FIELDATA FROM DATASET WHERE CATID = 2; 

但它没有给出理想的结果。

是否可以进行字符串操作以使输出成为 前者的营销,销售,后者只是营销

总结输入模式

 number1@text1;number2@text2;number3@text; 

,输出应为

 text1, text2, text3

2 个答案:

答案 0 :(得分:1)

显然,没有简单的方法可以根据当前的MySQL函数来匹配您的期望。

根据“@”和“;”的分隔符,这是一个符合您期望的野蛮解决方案。

示例SQL:

-- data
CREATE TABLE test.DATASET ( ID INT NOT NULL, U_NAME VARCHAR(45) NULL, FIELDATA VARCHAR(255) NULL, PRIMARY KEY (ID)); 
INSERT INTO test.DATASET (ID, U_NAME, FIELDATA) VALUES ('1', 'ALPHA', '21@Marketing;31@Sales'); 
INSERT INTO test.DATASET (ID, U_NAME, FIELDATA) VALUES ('2', 'BETA', '21@Marketing');

-- Query wanted, which can handle up to 5 secsions
SELECT 
    FIELDATA, 
    CONCAT_WS(
        ', ',
        IF((@tmp:=SUBSTRING_INDEX( SUBSTRING_INDEX(FIELDATA, '@', -5), ';', 1)) LIKE '%@%', NULL, @tmp),
        IF((@tmp:=SUBSTRING_INDEX( SUBSTRING_INDEX(FIELDATA, '@', -4), ';', 1)) LIKE '%@%', NULL, @tmp),
        IF((@tmp:=SUBSTRING_INDEX( SUBSTRING_INDEX(FIELDATA, '@', -3), ';', 1)) LIKE '%@%', NULL, @tmp),
        IF((@tmp:=SUBSTRING_INDEX( SUBSTRING_INDEX(FIELDATA, '@', -2), ';', 1)) LIKE '%@%', NULL, @tmp),
        IF((@tmp:=SUBSTRING_INDEX( SUBSTRING_INDEX(FIELDATA, '@', -1), ';', 1)) LIKE '%@%', NULL, @tmp)
    ) output
FROM  test.DATASET JOIN (SELECT @tmp := NULL) v;

- 需要查询,最多可以处理2秒 选择     FIELDATA,     CONCAT_WS(         ',',         IF((@ tmp:= SUBSTRING_INDEX(SUBSTRING_INDEX(FIELDATA,'@', - 2),';',1))LIKE'%@%',NULL,@ tmp),         IF((@ tmp:= SUBSTRING_INDEX(SUBSTRING_INDEX(FIELDATA,'@', - 1),';',1))LIKE'%@%',NULL,@ tmp)         )输出 FROM test.DATASET JOIN(SELECT @tmp:= NULL)v;

输出:

mysql> -- Query wanted, which can handle up to 5 secsions
mysql> SELECT
    ->     FIELDATA,
    ->     CONCAT_WS(
    ->         ', ',
    ->         IF((@tmp:=SUBSTRING_INDEX( SUBSTRING_INDEX(FIELDATA, '@', -5), ';', 1)) LIKE '%@%', NULL, @tmp),
    ->         IF((@tmp:=SUBSTRING_INDEX( SUBSTRING_INDEX(FIELDATA, '@', -4), ';', 1)) LIKE '%@%', NULL, @tmp),
    ->         IF((@tmp:=SUBSTRING_INDEX( SUBSTRING_INDEX(FIELDATA, '@', -3), ';', 1)) LIKE '%@%', NULL, @tmp),
    ->         IF((@tmp:=SUBSTRING_INDEX( SUBSTRING_INDEX(FIELDATA, '@', -2), ';', 1)) LIKE '%@%', NULL, @tmp),
    ->         IF((@tmp:=SUBSTRING_INDEX( SUBSTRING_INDEX(FIELDATA, '@', -1), ';', 1)) LIKE '%@%', NULL, @tmp)
    ->     ) output
    -> FROM  test.DATASET JOIN (SELECT @tmp := NULL) v;
+-----------------------+------------------+
| FIELDATA              | output           |
+-----------------------+------------------+
| 21@Marketing;31@Sales | Marketing, Sales |
| 21@Marketing          | Marketing        |
+-----------------------+------------------+
2 rows in set (0.00 sec)

mysql> -- Query wanted, which can handle up to 2 secsions
mysql> SELECT
    ->     FIELDATA,
    ->     CONCAT_WS(
    ->         ', ',
    ->         IF((@tmp:=SUBSTRING_INDEX( SUBSTRING_INDEX(FIELDATA, '@', -2), ';', 1)) LIKE '%@%', NULL, @tmp),
    ->         IF((@tmp:=SUBSTRING_INDEX( SUBSTRING_INDEX(FIELDATA, '@', -1), ';', 1)) LIKE '%@%', NULL, @tmp)
    ->         ) output
    -> FROM test.DATASET JOIN (SELECT @tmp := NULL) v;
+-----------------------+------------------+
| FIELDATA              | output           |
+-----------------------+------------------+
| 21@Marketing;31@Sales | Marketing, Sales |
| 21@Marketing          | Marketing        |
+-----------------------+------------------+
2 rows in set (0.00 sec)

答案 1 :(得分:1)

这是我对你的问题的尝试。我在网上找到了一些功能(我稍后会把这些功能放在一起)并将它们组合在一起以使其适合您的特定需求:您需要获得一个包含2级分隔符的干净字符串(@和)。

见下文:

DELIMITER $$

CREATE FUNCTION splitter(x VARCHAR(255), delim VARCHAR(12), pos INT)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
       LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
       delim, '');
END$$

CREATE FUNCTION substrCount(s VARCHAR(255), ss VARCHAR(255)) 
RETURNS tinyint(3) unsigned
READS SQL DATA
BEGIN
  DECLARE count TINYINT(3) UNSIGNED;
  DECLARE offset TINYINT(3) UNSIGNED;
  DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET s = NULL;
  SET count = 0;
  SET offset = 1;
  REPEAT
    IF NOT ISNULL(s) AND offset > 0 THEN
      SET offset = LOCATE(ss, s, offset);
      IF offset > 0 THEN
        SET count = count + 1;
        SET offset = offset + 1;
      END IF;
    END IF;
   UNTIL ISNULL(s) OR offset = 0 END REPEAT;
   RETURN count;
END$$

CREATE FUNCTION split_str(x varchar(255), delim varchar(12), delim2 varchar(12), return_separator varchar(12)) RETURNS varchar(255)
BEGIN
  SET @Valcount = substrCount(x,delim)+1;
  SET @v1=0;
  SET @v2='';
  WHILE (@v1 < @Valcount) DO
    set @val = splitter(x,delim,@v1+1);
    if @v1 = 0 then
      SET @v2 = world.split_str(@val,delim2,2);
    else
      SET @v2 = concat(@v2,return_separator,world.split_str(@val,delim2,2));
    end if;
    SET @v1 = @v1 + 1;
  END WHILE;
  return @v2;
END$$
DELIMITER ;

然后,你可以像下面一样使用它,假设你有一个表t2,其字段f2包含你的样本字符串&#34; number1 @ text1; number2 @ text2; number3 @ text;&#34;:< / p>

select split_str(f2,';','@',', '), f2 from t2

结果将是:

text1, text2, text

正如所承认的那样,作者:

Andrew Hanna on August 24 2006 8:04pm

创建的函数substrCount

Federico Cargnelutti on 2009

创建的功能拆分器

mtlseo on 2012

创建的功能split_str