相当于explode()在MySQL中使用字符串

时间:2011-05-08 16:09:47

标签: mysql sql

在MySQL中,我希望能够在另一个值= '31 - 7'时搜索'7 - 31'。我会用什么语法来分解MySQL中的字符串?在PHP中,我可能会使用explode(' - ',$string)并将它们组合在一起。有没有办法在MySQL中这样做?

背景:我正在使用体育比分,并且想要尝试得分相同(并且也在同一天)的比赛 - 每个团队的列出分数与对手的数据库记录相比是向后的。

理想的MySQL调用是:

Where opponent1.date  = opponent2.date
  AND opponent1.score = opponent2.score

opponent2.score需要opponent1.score向后)。

11 个答案:

答案 0 :(得分:63)

MYSQL没有内置explode()函数。但是你可以轻松地向你的数据库添加类似的函数,然后从php查询中使用它。该功能将如下所示:

CREATE FUNCTION SPLIT_STRING(str VARCHAR(255), delim VARCHAR(12), pos INT)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, pos),
       LENGTH(SUBSTRING_INDEX(str, delim, pos-1)) + 1),
       delim, '');

用法:

SELECT SPLIT_STRING('apple, pear, melon', ',', 1)

上面的示例将返回apple。 我认为在MySQL中返回数组是不可能的,因此您必须在pos中明确指定要返回的事件。如果您成功使用它,请告诉我。

答案 1 :(得分:43)

我尝试使用SUBSTRING_INDEX(string,delimiter,count)

mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2);
-> 'www.mysql'

mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2);
-> 'mysql.com'

在mysql.com上查看更多信息 http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_substring-index

答案 2 :(得分:23)

您可以这种方式使用存储过程..

DELIMITER |

CREATE PROCEDURE explode( pDelim VARCHAR(32), pStr TEXT)                                
BEGIN                                
  DROP TABLE IF EXISTS temp_explode;                                
  CREATE TEMPORARY TABLE temp_explode (id INT AUTO_INCREMENT PRIMARY KEY NOT NULL, word VARCHAR(40));                                
  SET @sql := CONCAT('INSERT INTO temp_explode (word) VALUES (', REPLACE(QUOTE(pStr), pDelim, '\'), (\''), ')');                                
  PREPARE myStmt FROM @sql;                                
  EXECUTE myStmt;                                
END |   

DELIMITER ;
  • 示例电话:

     SET @str  = "The quick brown fox jumped over the lazy dog"; 
     SET @delim = " "; 
    
    CALL explode(@delim,@str);
    SELECT id,word FROM temp_explode;
    

答案 3 :(得分:17)

首先,您应该更改数据库结构 - 在这种情况下,得分是某种复合值,应该存储在两列中,例如。 score_hostscore_guest


MySQL不提供explode()等效项,但在这种情况下,您可以使用SUBSTRING()LOCATE()来切断主持人和访客的得分。

SELECT 
   CONVERT(SUBSTRING(score, 1, LOCATE('-',score) - 2) USING INTEGER) as score_host,
   CONVERT(SUBSTRING(score, LOCATE('-',score)+2) USING INTEGER) as score_guest
FROM ...;

CONVERT()用于将字符串"23"转换为数字23

答案 4 :(得分:5)

使用此功能。它就像一个魅力。替换" |"使用char来爆炸/拆分,值1,2,3等基于数据集中的条目数: Value_ONE | Value_TWO |。Value_THREE

SUBSTRING_INDEX(SUBSTRING_INDEX(`tblNAME`.`tblFIELD`, '|', 1), '|', -1) AS PSI,
SUBSTRING_INDEX(SUBSTRING_INDEX(`tblNAME`.`tblFIELD`, '|', 2), '|', -1) AS GPM,
SUBSTRING_INDEX(SUBSTRING_INDEX(`tblNAME`.`tblFIELD`, '|', 3), '|', -1) AS LIQUID

我希望这会有所帮助。

答案 5 :(得分:2)

正如@ arman-p所指出的那样,MYSQL没有爆炸()。但是,我认为所提出的解决方案要比它需要的复杂得多。要在给出逗号分隔的列表字符串(例如,要查找的表键列表)时进行快速检查,请执行以下操作:

SELECT 
    table_key, field_1, field_2, field_3
FROM
    my_table
WHERE
    field_3 = 'my_field_3_value'
    AND (comma_list = table_key
        OR comma_list LIKE CONCAT(table_key, ',%')
        OR comma_list LIKE CONCAT('%,', table_key, ',%')
        OR comma_list LIKE CONCAT('%,', table_key))

这假设您还需要检查表中的field_3。如果您不需要,请不要添加该条件。

答案 6 :(得分:2)

使用substring_index,在下面的示例中,我创建了一个列为score1和score2的表,score1为3-7,score2为7-3等,如图所示。以下查询能够使用“ - ”拆分并反转​​score2的顺序并与score1

进行比较
SELECT CONCAT(SUBSTRING_INDEX(score1,'-',1),
SUBSTRING_INDEX(score1,'-',-1)) as my_score1,
CONCAT(SUBSTRING_INDEX(score2,'-',-1),SUBSTRING_INDEX(score2,'-',1)) as my_score2
FROM test HAVING my_score1=my_score2

scores table

query results

答案 7 :(得分:1)

如果explode与foreach一起使用来构建一个新的字符串,你可以通过使用这样的while循环来模拟爆炸:

CREATE FUNCTION explode_and_loop(sep VARCHAR(),inputstring VARCHAR()) RETURNS VARCHAR() 
BEGIN
    DECLARE part,returnstring VARCHAR();
    DECLARE cnt,partsCnt INT();
    SET returnstring = '';
    SET partsCnt = ((LENGTH(inputstring ) - LENGTH(REPLACE(inputstring,sep,''))) DIV LENGTH(sep);
    SET cnt = 0;
    WHILE cnt <= partsCnt DO
        SET cnt = cnt + 1;
        SET part = SUBSTRING_INDEX(SUBSTRING_INDEX(inputstring ,sep,cnt),sep,-1);
        -- DO SOMETHING with the part eg make html:
        SET returnstring = CONCAT(returnstring,'<li>',part,'</li>')
    END WHILE;
    RETURN returnstring;
END

此示例将返回部件的html列表。 (必须添加所需的变量)

答案 8 :(得分:0)

我今天遇到了同样的问题并在下面解决了,请注意在我的情况下,我知道连接字符串中的项目数,因此我可以通过这种方式恢复它们:

set @var1=0;
set @var2=0;
SELECT SUBSTRING_INDEX('value1,value2', ',', 1) into @var1;
SELECT SUBSTRING_INDEX('value1,value2', ',', -1) into @var2;

变量@ var1和@ var2的值类似于explode()。

答案 9 :(得分:0)

This is actually a modified version of the selected answer in order to support Unicode characters but I don't have enough reputation to comment there.

CREATE FUNCTION SPLIT_STRING(str VARCHAR(255) CHARSET utf8, delim VARCHAR(12), pos INT) RETURNS varchar(255) CHARSET utf8
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, pos),
       CHAR_LENGTH(SUBSTRING_INDEX(str, delim, pos-1)) + 1),
       delim, '')

The modifications are the following:

  • The first parameter is set as utf8
  • The function is set to return utf8
  • The code uses CHAR_LENGTH() instead of LENGTH() to calculate the character length and not the byte length.

答案 10 :(得分:0)

我不确定这是否能完全回答问题(不是),但这是我为非常相似的问题想出的解决方案。我知道其他一些解决方案看起来更短,但是它们似乎比必要的更多地使用了SUBSTRING_INDEX()方式。在这里,我尝试每个定界符只使用一次LOCATE()。

-- *****************************************************************************
-- test_PVreplace

DROP FUNCTION IF EXISTS test_PVreplace;

delimiter //
CREATE FUNCTION test_PVreplace (
   str TEXT,   -- String to do search'n'replace on
   pv TEXT     -- Parameter/value pairs 'p1=v1|p2=v2|p3=v3'
   )
   RETURNS TEXT

-- Replace specific tags with specific values.

sproc:BEGIN
   DECLARE idx INT;
   DECLARE idx0 INT DEFAULT 1;   -- 1-origined, not 0-origined
   DECLARE len INT;
   DECLARE sPV TEXT;
   DECLARE iPV INT;
   DECLARE sP TEXT;
   DECLARE sV TEXT;

   -- P/V string *must* end with a delimiter.

   IF (RIGHT (pv, 1) <> '|') THEN
      SET pv = CONCAT (pv, '|');
      END IF;

   -- Find all the P/V pairs.

   SELECT LOCATE ('|', pv, idx0) INTO idx;
   WHILE (idx > 0) DO
      SET len = idx - idx0;
      SELECT SUBSTRING(pv, idx0, len) INTO sPV;

      -- Found a P/V pair.  Break it up.

      SELECT LOCATE ('=', sPV) INTO iPV;
      IF (iPV = 0) THEN
         SET sP = sPV;
         SET sV = '';
      ELSE
         SELECT SUBSTRING(sPV, 1, iPV-1) INTO sP;
         SELECT SUBSTRING(sPV, iPV+1) INTO sV;
         END IF;

      -- Do the substitution(s).

      SELECT REPLACE (str, sP, sV) INTO str;

      -- Do next P/V pair.

      SET idx0 = idx + 1;
      SELECT LOCATE ('|', pv, idx0) INTO idx;
      END WHILE;
   RETURN (str);
END//
delimiter ;

SELECT test_PVreplace ('%one% %two% %three%', '%one%=1|%two%=2|%three%=3');
SELECT test_PVreplace ('%one% %two% %three%', '%one%=I|%two%=II|%three%=III');
SELECT test_PVreplace ('%one% %two% %three% - %one% %two% %three%', '%one%=I|%two%=II|%three%=III');
SELECT test_PVreplace ('%one% %two% %three% - %one% %two% %three%', '');
SELECT test_PVreplace ('%one% %two% %three% - %one% %two% %three%', NULL);
SELECT test_PVreplace ('%one% %two% %three%', '%one%=%two%|%two%=%three%|%three%=III');