【问题标题】:How to split the name string in mysql?如何在mysql中拆分名称字符串?
【发布时间】:2013-02-03 17:16:24
【问题描述】:

如何在mysql中拆分名称字符串?

例如:

name
-----
Sachin ramesh tendulkar
Rahul dravid

拆分名称如firstname,middlename,lastname:

firstname   middlename    lastname
---------  ------------   ------------
sachin     ramesh         tendulkar
rahul      dravid

【问题讨论】:

  • 当您的表格正确规范化时,您对此没有任何问题。 您不需要拆分值。
  • @JW。不幸的是,名字特别难取。 kalzumeus.com/2010/06/17/…
  • @Madhav 如果任何答案解决了您的问题,请单击已解决...提示提示;)
  • 试图找出名字的一部分是“名字”或“姓氏”是悲伤的道路。并非所有名称都是由空格分隔的两个“单词”。考虑 Eddie Van Halen(姓氏 2 个字)或 Zack de la Rocha(姓氏 3 个字)或 Jerry Lee Lewis(姓氏 2 个字)。不要忘记像 Olivia Newton-John 和 Yo-Yo Ma 这样的连字符或像 Sinead O'Connor 这样的撇号。你不会有一个基于模式的一致准确的方法来完成这项任务。

标签: mysql sql split substring


【解决方案1】:

我已将此答案分为两 (2) 种方法。第一种方法会将您的全名字段分为名字、中间名和姓氏。如果没有中间名,中间名将显示为 NULL。

SELECT
   SUBSTRING_INDEX(SUBSTRING_INDEX(fullname, ' ', 1), ' ', -1) AS first_name,
   If(  length(fullname) - length(replace(fullname, ' ', ''))>1,  
       SUBSTRING_INDEX(SUBSTRING_INDEX(fullname, ' ', 2), ' ', -1) ,NULL) 
           as middle_name,
   SUBSTRING_INDEX(SUBSTRING_INDEX(fullname, ' ', 3), ' ', -1) AS last_name
FROM registeredusers

第二种方法将中间名视为姓氏的一部分。我们只会从您的全名字段中选择名字和姓氏列。

SELECT
   SUBSTRING_INDEX(SUBSTRING_INDEX(fullname, ' ', 1), ' ', -1) AS first_name,
    TRIM( SUBSTR(fullname, LOCATE(' ', fullname)) ) AS last_name
FROM registeredusers

你可以用 substr、locate、substring_index 等做很多很酷的事情。查看手册是否有一些真正的困惑。 http://dev.mysql.com/doc/refman/5.0/en/string-functions.html

【讨论】:

  • 天哪,英特尔刚刚让我觉得自己拥有 mysql 专业技能。我已经完全删除了 PHP 处理并在一个查询中转换了 100 行逻辑。这太棒了!
  • 真的很好。正是我所需要的,并且可能比他希望的更好地解决了提问者问题事件,因为在两个词的情况下,只有名字和姓氏被设置,而不是名字和中间名。
  • 第一种方法对我帮助很大。我看到的唯一问题是姓“St. George”被选为中间名“St.”。
  • 您好先生,我知道这是一个旧线程。如果这个人有扩展名怎么办?
  • @TrafalgarDLaw 我在上面发布了一个解决方案。 - stackoverflow.com/a/44802256/3542883
【解决方案2】:

MySQL 中没有字符串拆分功能。所以你必须创建自己的功能。这将对您有所帮助。 More details at this link.

功能:

CREATE FUNCTION SPLIT_STR(
  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, '');

用法:

SELECT SPLIT_STR(string, delimiter, position)

示例:

SELECT SPLIT_STR('a|bb|ccc|dd', '|', 3) as third;

+-------+
| third |
+-------+
| ccc   |
+-------+

【讨论】:

  • 这是迄今为止最好的答案
  • 最佳答案,我绝对用它?✨
  • 这对我来说是最好的解决方案
【解决方案3】:

好吧,我用的都没有用,所以我决定创建一个真正简单的拆分函数,希望对您有所帮助:

DECLARE inipos INTEGER;
DECLARE endpos INTEGER;
DECLARE maxlen INTEGER;
DECLARE item VARCHAR(100);
DECLARE delim VARCHAR(1);

SET delim = '|';
SET inipos = 1;
SET fullstr = CONCAT(fullstr, delim);
SET maxlen = LENGTH(fullstr);

REPEAT
    SET endpos = LOCATE(delim, fullstr, inipos);
    SET item =  SUBSTR(fullstr, inipos, endpos - inipos);

    IF item <> '' AND item IS NOT NULL THEN           
        USE_THE_ITEM_STRING;
    END IF;
    SET inipos = endpos + 1;
UNTIL inipos >= maxlen END REPEAT;

【讨论】:

  • 您还必须检查最后一项的endpos;因为对于最后一项,endpos 将为零,并且此 while 循环将永远持续下去。我的建议是最初将布尔变量设置为 false 并在 endpos = 0 和退出直到循环中将其设置为 true 并检查此标志 = true。
【解决方案4】:

这是我使用的拆分功能:

--
-- split function
--    s   : string to split
--    del : delimiter
--    i   : index requested
--

DROP FUNCTION IF EXISTS SPLIT_STRING;

DELIMITER $

CREATE FUNCTION 
   SPLIT_STRING ( s VARCHAR(1024) , del CHAR(1) , i INT)
   RETURNS VARCHAR(1024)
   DETERMINISTIC -- always returns same results for same input parameters
    BEGIN

        DECLARE n INT ;

        -- get max number of items
        SET n = LENGTH(s) - LENGTH(REPLACE(s, del, '')) + 1;

        IF i > n THEN
            RETURN NULL ;
        ELSE
            RETURN SUBSTRING_INDEX(SUBSTRING_INDEX(s, del, i) , del , -1 ) ;        
        END IF;

    END
$

DELIMITER ;


SET @agg = "G1;G2;G3;G4;" ;

SELECT SPLIT_STRING(@agg,';',1) ;
SELECT SPLIT_STRING(@agg,';',2) ;
SELECT SPLIT_STRING(@agg,';',3) ;
SELECT SPLIT_STRING(@agg,';',4) ;
SELECT SPLIT_STRING(@agg,';',5) ;
SELECT SPLIT_STRING(@agg,';',6) ;

【讨论】:

  • 这对我来说效果很好,并且没有像接受的答案那样导致无限循环(不清楚为什么) - 但它不适用于空格作为分隔符。对于遇到此问题的任何人 - 请查看 stackoverflow.com/questions/2696884/…
  • 如果您的分隔符大于一,那么您还需要将长度差除以您的分隔符长度。
  • 将定义从 SPLIT_STRING ( s VARCHAR(1024) , del CHAR(1) , i INT) 更改为 SPLIT_STRING ( s VARCHAR(1024) , del VARCHAR(1) , i INT) 并且它适用于空格
【解决方案5】:

你也可以使用 bewlo one:

SELECT SUBSTRING_INDEX(Name, ' ', 1) AS fname,
SUBSTRING_INDEX(SUBSTRING_INDEX(Name,' ', 2), ' ',-1) AS mname,
SUBSTRING_INDEX(Name, ' ', -1) as lname FROM mytable;

【讨论】:

  • 这对我有用。我觉得这是不好的做法,但我运行了相同的查询来复制我的 case 语句,发现这种方法的速度是原来的两倍。谢谢。
【解决方案6】:
select (case when locate('(', LocationName) = 0 
        then 
            horse_name
        else 
           left(LocationName, locate('(', LocationName) - 1)
       end) as Country            
from   tblcountry;

【讨论】:

    【解决方案7】:

    获取空格分隔符的第二个实例之后的其余字符串

    SELECT
       SUBSTRING_INDEX(SUBSTRING_INDEX('Sachin ramesh tendulkar', ' ', 1), ' ', -1) AS first_name, 
           SUBSTRING_INDEX(SUBSTRING_INDEX('Sachin ramesh tendulkar', ' ', 2), ' ', -1) 
               AS middle_name,
       SUBSTRING('Sachin ramesh tendulkar',LENGTH(SUBSTRING_INDEX('Sachin ramesh tendulkar', ' ', 2))+1) AS last_name
    

    【讨论】:

      【解决方案8】:
      SELECT
          p.fullname AS 'Fullname',
          SUBSTRING_INDEX(p.fullname, ' ', 1) AS 'Firstname',
          SUBSTRING(p.fullname, LOCATE(' ',p.fullname), 
              (LENGTH(p.fullname) - (LENGTH(SUBSTRING_INDEX(p.fullname, ' ', 1)) + LENGTH(SUBSTRING_INDEX(p.fullname, ' ', -1))))
          ) AS 'Middlename',
          SUBSTRING_INDEX(p.fullname, ' ', -1) AS 'Lastname',
          (LENGTH(p.fullname) - LENGTH(REPLACE(p.fullname, ' ', '')) + 1) AS 'Name Qt'
      FROM people AS p
      LIMIT 100; 
      

      说明:

      查找名字和姓氏很容易,您只需使用 SUBSTR_INDEX 函数 魔术发生在中间名中,其中使用 SUBSTR 和 Locate 来查找第一个空格位置和全名的 LENGTH - (LENGTH firstname + LENGTH lastname) 以获取所有中间名。

      请注意,名字和姓氏的长度是使用 SUBSTR_INDEX 计算的

      【讨论】:

        【解决方案9】:
        concat(upper(substring(substring_index(NAME, ' ', 1) FROM 1 FOR 1)), lower(substring(substring_index(NAME, ' ', 1) FROM 2 FOR length(substring_index(NAME, ' ', 1))))) AS fname,
        CASE 
        WHEN length(substring_index(substring_index(NAME, ' ', 2), ' ', -1)) > 2 THEN 
          concat(upper(substring(substring_index(substring_index(NAME, ' ', 2), ' ', -1) FROM 1 FOR 1)), lower(substring(substring_index(substring_index(f.nome, ' ', 2), ' ', -1) FROM 2 FOR length(substring_index(substring_index(f.nome, ' ', 2), ' ', -1)))))
          ELSE 
          CASE 
          WHEN length(substring_index(substring_index(f.nome, ' ', 3), ' ', -1)) > 2 THEN 
            concat(upper(substring(substring_index(substring_index(f.nome, ' ', 3), ' ', -1) FROM 1 FOR 1)), lower(substring(substring_index(substring_index(f.nome, ' ', 3), ' ', -1) FROM 2 FOR length(substring_index(substring_index(f.nome, ' ', 3), ' ', -1)))))
          END 
        END 
        AS mname
        

        【讨论】:

          【解决方案10】:

          您可以使用common_schematokenize 函数。有关这方面的更多信息,请点击链接。你的代码最终会是这样的:

          call tokenize(name, ' ');

          但是,请注意,空格不是名字和姓氏的可靠分隔符。例如。在西班牙,通常有两个姓氏。

          【讨论】:

          • 我不知道这个库,很棒的提示,谢谢
          【解决方案11】:
          CREATE DEFINER=`root`@`localhost` FUNCTION `getNameInitials`(`fullname` VARCHAR(500), `separator` VARCHAR(1)) RETURNS varchar(70) CHARSET latin1
              DETERMINISTIC
          BEGIN
          DECLARE `result` VARCHAR(500) DEFAULT '';
          DECLARE `position` TINYINT;
          
          
          
          SET `fullname` = TRIM(`fullname`);
          
          SET `position` = LOCATE(`separator`, `fullname`);
          
          IF NOT `position`
          THEN RETURN LEFT(`fullname`,1);
          END IF;
          
          SET `fullname` = CONCAT(`fullname`,`separator`);
          SET `result` = LEFT(`fullname`, 1);
          
          cycle: LOOP
              SET `fullname` = SUBSTR(`fullname`, `position` + 1);
              SET `position` = LOCATE(`separator`, `fullname`);
          
              IF NOT `position` OR NOT LENGTH(`fullname`)
              THEN LEAVE cycle;
              END IF;
          
              SET `result` = CONCAT(`result`,LEFT(`fullname`, 1));
             -- SET `result` = CONCAT_WS(`separator`, `result`, `buffer`);
          END LOOP cycle;
          
          RETURN upper(`result`);
          END
          

          1.在mysql中执行这个函数。 2.这将创建一个函数。现在你可以在任何你想要的地方使用这个功能了。

           SELECT `getNameInitials`('Kaleem Ul Hassan', ' ') AS `NameInitials`;
          

          3。上面的 getNameInitails 第一个参数是要过滤的字符串,第二个参数是要分隔字符串的旁观者角色。 4.在上面的例子中,'Kaleem Ul Hassan'是名字,我想得到首字母,我的分隔符是空格''。

          【讨论】:

            【解决方案12】:

            我们将课程名称和章节名称的值存储在单列章节名称中。

            值存储如下:“JAVA:多态性”

            您需要检索 CourseName : JAVA 和 ChapterName : Polymorphism

            下面是要检索的 SQL 选择查询。

                   SELECT   
                      SUBSTRING_INDEX(SUBSTRING_INDEX(ChapterName, ' ', 1), ' ', -1) AS 
                   CourseName,
            
                   REPLACE(TRIM(SUBSTR(ChapterName, LOCATE(':', ChapterName)) ),':','') AS 
                   ChapterName
                   FROM Courses where `id`=1;
            

            如果对此有任何疑问,请告诉我。

            【讨论】:

              【解决方案13】:

              获取空格分隔符的第二个实例之后的其余字符串:

              SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(MsgRest, ' ', 1), ' ', -1) AS EMailID
              ,  SUBSTRING_INDEX(SUBSTRING_INDEX(MsgRest, ' ', 2), ' ', -1) AS DOB
              ,  IF(
                  LOCATE(' ', `MsgRest`) > 0,
                  TRIM(SUBSTRING(SUBSTRING(`MsgRest`, LOCATE(' ', `MsgRest`) +1), 
                       LOCATE(' ', SUBSTRING(`MsgRest`, LOCATE(' ', `MsgRest`) +1)) +1)),
                  NULL
              ) AS Person
              FROM inbox
              

              【讨论】:

                【解决方案14】:

                DELIMITER $$
                
                DROP FUNCTION IF EXISTS `split_name`$$
                
                CREATE FUNCTION split_name (p_fullname TEXT, p_part INTEGER)
                RETURNS TEXT
                    READS SQL DATA
                BEGIN
                    DECLARE v_words INT UNSIGNED;
                    DECLARE v_name TEXT;
                
                    SET p_fullname=RTRIM(LTRIM(p_fullname));
                
                    SET v_words=(SELECT SUM(LENGTH(p_fullname) - LENGTH(REPLACE(p_fullname, ' ', ''))+1));
                
                    IF v_words=1 THEN 
                        IF p_part=1 THEN
                            SET v_name=p_fullname;
                        ELSEIF p_part=2 THEN
                            SET v_name=NULL;
                        ELSEIF p_part=3 THEN
                            SET v_name=NULL;
                        ELSE
                            SET v_name=NULL;
                        END IF; 
                    ELSEIF v_words=2 THEN 
                        IF p_part=1 THEN
                            SET v_name=SUBSTRING(p_fullname, 1, LOCATE(' ', p_fullname) - 1);
                        ELSEIF p_part=2 THEN
                            SET v_name=SUBSTRING(p_fullname, LOCATE(' ', p_fullname) + 1);
                        ELSEIF p_part=3 THEN
                            SET v_name=NULL;
                        ELSE
                            SET v_name=NULL;
                        END IF; 
                    ELSEIF v_words=3 THEN 
                        IF p_part=1 THEN
                            SET v_name=SUBSTRING(p_fullname, 1, LOCATE(' ', p_fullname) - 1);
                        ELSEIF p_part=2 THEN
                            SET p_fullname=SUBSTRING(p_fullname, LOCATE(' ', p_fullname) + 1);
                            SET v_name=SUBSTRING(p_fullname, 1, LOCATE(' ', p_fullname) - 1);
                        ELSEIF p_part=3 THEN
                            SET p_fullname=REVERSE (SUBSTRING(p_fullname, LOCATE(' ', p_fullname) + 1));
                            SET p_fullname=SUBSTRING(p_fullname, 1, LOCATE(' ', p_fullname) - 1);
                            SET v_name=REVERSE(p_fullname);
                        ELSE
                            SET v_name=NULL;
                        END IF; 
                    ELSEIF v_words>3 THEN 
                        IF p_part=1 THEN
                            SET v_name=SUBSTRING(p_fullname, 1, LOCATE(' ', p_fullname) - 1);
                        ELSEIF p_part=2 THEN
                            SET p_fullname=REVERSE(SUBSTRING(p_fullname, LOCATE(' ', p_fullname) + 1));
                            SET p_fullname=SUBSTRING(p_fullname, LOCATE(' ', p_fullname,SUBSTRING_INDEX(p_fullname,' ',1)+1) + 1);
                            SET v_name=REVERSE(p_fullname);
                        ELSEIF p_part=3 THEN
                            SET p_fullname=REVERSE (SUBSTRING(p_fullname, LOCATE(' ', p_fullname) + 1));
                            SET p_fullname=SUBSTRING(p_fullname, 1, LOCATE(' ', p_fullname) - 1);
                            SET v_name=REVERSE(p_fullname);
                        ELSE
                            SET v_name=NULL;
                        END IF;
                    ELSE
                        SET v_name=NULL;
                    END IF;
                 RETURN v_name; 
                END;
                

                SELECT split_name('Md. Obaidul Haque Sarker',1) AS first_name,
                split_name('Md. Obaidul Haque Sarker',2) AS middle_name,
                split_name('Md. Obaidul Haque Sarker',3) AS last_name
                

                【讨论】:

                  【解决方案15】:

                  首先创建过程如下:

                  CREATE DEFINER=`root`@`%` PROCEDURE `sp_split`(str nvarchar(6500), dilimiter varchar(15), tmp_name varchar(50))
                  BEGIN
                  
                      declare end_index   int;
                      declare part        nvarchar(6500);
                      declare remain_len  int;
                  
                      set end_index      = INSTR(str, dilimiter);
                  
                      while(end_index   != 0) do
                  
                          /* Split a part */
                          set part       = SUBSTRING(str, 1, end_index - 1);
                  
                          /* insert record to temp table */
                          call `sp_split_insert`(tmp_name, part);
                  
                          set remain_len = length(str) - end_index;
                          set str = substring(str, end_index + 1, remain_len);
                  
                          set end_index  = INSTR(str, dilimiter);
                  
                      end while;
                  
                      if(length(str) > 0) then
                  
                          /* insert record to temp table */
                          call `sp_split_insert`(tmp_name, str);
                  
                      end if;
                  
                  END
                  

                  创建过程如下:

                  CREATE DEFINER=`root`@`%` PROCEDURE `sp_split_insert`(tb_name varchar(255), tb_value nvarchar(6500))
                  BEGIN
                      SET @sql = CONCAT('Insert Into ', tb_name,'(item) Values(?)'); 
                      PREPARE s1 from @sql;
                      SET @paramA = tb_value;
                      EXECUTE s1 USING @paramA;
                  END
                  

                  如何调用测试

                  CREATE DEFINER=`root`@`%` PROCEDURE `test_split`(test_text nvarchar(255))
                  BEGIN
                  
                      create temporary table if not exists tb_search
                          (
                              item nvarchar(6500)
                          );
                  
                      call sp_split(test_split, ',', 'tb_search');
                  
                      select * from tb_search where length(trim(item)) > 0;
                  
                      drop table tb_search;
                  
                  END
                  
                  
                  call `test_split`('Apple,Banana,Mengo');
                  

                  【讨论】:

                    【解决方案16】:

                    结合这里的几个答案来创建一个返回字符串部分的 SP。

                    drop procedure if exists SplitStr;
                    DELIMITER ;;
                    CREATE PROCEDURE `SplitStr`(IN Str VARCHAR(2000), IN Delim VARCHAR(1))  
                        BEGIN
                            DECLARE inipos INT;
                            DECLARE endpos INT;
                            DECLARE maxlen INT;
                            DECLARE fullstr VARCHAR(2000);
                            DECLARE item VARCHAR(2000);
                            create temporary table if not exists tb_split
                            (
                                item varchar(2000)
                            );
                    
                    
                    
                            SET inipos = 1;
                            SET fullstr = CONCAT(Str, delim);
                            SET maxlen = LENGTH(fullstr);
                    
                            REPEAT
                                SET endpos = LOCATE(delim, fullstr, inipos);
                                SET item =  SUBSTR(fullstr, inipos, endpos - inipos);
                    
                                IF item <> '' AND item IS NOT NULL THEN           
                                    insert into tb_split values(item);
                                END IF;
                                SET inipos = endpos + 1;
                            UNTIL inipos >= maxlen END REPEAT;
                    
                            SELECT * from tb_split;
                            drop table tb_split;
                        END;;
                    DELIMITER ;
                    

                    【讨论】:

                      【解决方案17】:

                      根据之前的答案,做一些修改...

                      注意:

                      p_delimiter 必须是 VARCHAR(1) 可能是 CHAR(1) 如果是 ' '(空格)给出 ''(删除空格并返回空字符串)

                      而不是使用LENGTH 我更喜欢CHAR_LENGTH,这对于像UTF 这样的多字节字符是安全的

                      DROP FUNCTION IF EXISTS FN_SPLIT_STR;
                      
                      DELIMITER ;;
                      
                      CREATE FUNCTION FN_SPLIT_STR(
                          p_input VARCHAR(2000), p_delimiter VARCHAR(1), p_position INT
                      )
                          RETURNS VARCHAR(2000)
                          DETERMINISTIC
                      BEGIN
                          DECLARE chunks INT;
                          SET chunks := CHAR_LENGTH(p_input) - CHAR_LENGTH(REPLACE(p_input, p_delimiter, '')) + 1;
                      
                          IF p_position > chunks THEN
                              RETURN NULL;
                          END IF;
                      
                          RETURN SUBSTRING_INDEX(SUBSTRING_INDEX(p_input, p_delimiter, p_position), p_delimiter, -1);
                      END;;
                      
                      DELIMITER ;
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 2018-02-22
                        • 1970-01-01
                        • 1970-01-01
                        • 2015-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多