mysql에서 이름 문자열을 분할하는 방법은 무엇입니까?


103

mysql에서 이름 문자열을 분할하는 방법은 무엇입니까?

예 :

name
-----
Sachin ramesh tendulkar
Rahul dravid

다음과 같이 이름을 분할합니다 firstname,middlename,lastname.

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

4
테이블이 제대로 정규화되면 아무런 문제가 없습니다. 값을 분할 할 필요가 없습니다.
John Woo


2
@JW. 안타깝게도 이름은 특히 어렵습니다. kalzumeus.com/2010/06/17/…
Matt Ball

1
답변 중 하나가 귀하의 질문에 클릭이 해결 ... 힌트 힌트를 해결하는 경우 @Madhav)
제시 C

답변:


181

이 답변을 두 가지 방법으로 분리했습니다. 첫 번째 방법은 전체 이름 필드를 이름, 중간 및 성으로 구분합니다. 중간 이름이 없으면 중간 이름이 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


6
인텔이 방금 mysql 프로 기술을 사용하여 인간이 된 것처럼 느끼게 만들었습니다. 저는 PHP 처리를 완전히 제거하고 하나의 쿼리로 100 줄의 논리를 돌 렸습니다. 이것은 놀랍다!
TeaCupApp 2014

1
정말 좋습니다. 내가 필요한 것을 정확히했고 아마도 그가 원하는 것보다 더 나은 질문자 문제 이벤트를 해결했습니다. 두 단어의 경우 이름과 성만 이름과 중간 이름이 아닌 설정되기 때문입니다.
Jānis Gruzis

첫 번째 방법은 저에게 많은 도움이되었습니다. 내가 본 유일한 문제는 성 "St. George"가 중간 이름 "St."로 선택되었습니다.
Joe M.

1
안녕하세요 선생님 저는 이것이 오래된 스레드라는 것을 알고 있습니다. 그 사람이 내선 이름을 가지고 있다면 어떨까요?
Trafalgar D Law

1
@TrafalgarDLaw 위의 솔루션을 게시했습니다. - stackoverflow.com/a/44802256/3542883
주니어

22

글쎄, 내가 사용한 것은 아무것도 없었기 때문에 정말 간단한 분할 함수를 만들기로 결정했습니다.

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;

18

내가 사용하는 분할 기능은 다음과 같습니다.

--
-- 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/… 를보십시오.
Max

15

MySQL에는 문자열 분할 기능이 없습니다. 그래서 당신은 자신의 함수를 만들어야합니다. 이것은 당신을 도울 것입니다. 자세한 내용은이 링크를 참조하십시오 .

함수:

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   |
+-------+

이는 지금까지 가장 좋은 대답입니다
Hydrocat

베스트 답변, 저는 확실히 그것을 사용합니다 👍✨
Rizki Noor Hidayat Wijaya

11

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 문을 복제 한 결과이 접근 방식이 두 배 빠르다는 것을 알았습니다. 감사.
jDub9

3
select (case when locate('(', LocationName) = 0 
        then 
            horse_name
        else 
           left(LocationName, locate('(', LocationName) - 1)
       end) as Country            
from   tblcountry;

2

공백 구분 기호의 두 번째 인스턴스 뒤에있는 나머지 문자열을 가져 오려면

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

2
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 함수를 사용하기 만하면됩니다. Magic은 중간 이름에서 발생하며, 여기서 SUBSTR을 사용하여 첫 번째 공백 위치를 찾고 전체 이름의 LENGTH-(LENGTH firstname + LENGTH lastname) 모든 중간 이름을 가져옵니다.

성과 이름의 LENGTH는 SUBSTR_INDEX를 사용하여 계산되었습니다.


2
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

1
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'은 이름이고 이니셜을 얻고 싶습니다. 구분자는 공백 ''입니다.


1

강좌 이름과 장 이름의 값을 ChapterName 단일 열에 저장했습니다.

다음과 같이 저장된 값 : "JAVA : Polymorphism"

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;

이것에 대한 질문이 있으면 알려주십시오.


0

공백 구분 기호의 두 번째 인스턴스 뒤에있는 나머지 문자열을 가져 오려면 다음을 수행하십시오.

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

0

당신은 사용할 수 common_schema을 하고 사용하는 tokenize기능. 이에 대한 자세한 내용은 링크를 따르십시오. 코드는 다음과 같이 끝납니다.

call tokenize(name, ' ');

그러나 공백은 성과 이름에 대한 신뢰할 수있는 구분 기호가 아닙니다. 예 : 스페인에서는 두 개의 성을 갖는 것이 일반적입니다.


0

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

0

다음과 같이 첫 번째 생성 절차 :

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');

0

여기에 몇 가지 답변을 결합하여 문자열의 일부를 반환하는 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 ;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.