Comment diviser la chaîne de nom dans mysql?

103

Comment diviser la chaîne de nom dans mysql?

Par exemple:

name
-----
Sachin ramesh tendulkar
Rahul dravid

Divisez le nom comme firstname,middlename,lastname:

firstname   middlename    lastname
---------  ------------   ------------
sachin     ramesh         tendulkar
rahul      dravid
Madhav
la source
4
lorsque vos tables sont correctement normalisées, vous n'avez aucun problème à ce sujet. Vous n'avez pas besoin de diviser les valeurs.
John Woo
2
@JW. malheureusement, les noms en particulier sont difficiles. kalzumeus.com/2010/06/17/…
Matt Ball
1
@Madhav Si l'une des réponses a résolu votre question, cliquez sur résolu ... hint hint;)
Jesse C

Réponses:

181

J'ai séparé cette réponse en deux (2) méthodes. La première méthode séparera votre champ de nom complet en prénom, deuxième et nom de famille. Le deuxième prénom s'affichera comme NULL s'il n'y a pas de deuxième prénom.

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

Cette deuxième méthode considère le deuxième prénom comme faisant partie du nom de famille. Nous ne sélectionnerons qu'une colonne de prénom et de nom dans votre champ de nom complet.

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

Il y a un tas de choses intéressantes que vous pouvez faire avec substr, Locate, substring_index, etc. Vérifiez le manuel pour une certaine confusion. http://dev.mysql.com/doc/refman/5.0/en/string-functions.html

Jesse C
la source
6
Gosh que Intel vient de me faire sentir super humain avec les compétences mysql pro. J'ai complètement supprimé le traitement PHP et transformé 100 lignes de logique en une seule requête. Ceci est incroyable!
TeaCupApp
1
Vraiment sympa. A fait exactement ce dont j'avais besoin et a probablement résolu le problème des demandeurs mieux qu'il ne l'aurait souhaité, car dans le cas de deux mots, seuls le prénom et le nom sont définis, pas le prénom et le nom intermédiaire.
Jānis Gruzis
La première méthode m'a beaucoup aidé. Le seul problème que j'ai vu était un nom de famille "St. George" a été choisi comme deuxième prénom "St.".
Joe M.
1
Bonjour monsieur, je sais que c'est un vieux fil. Et si la personne a un nom d'extension?
Trafalgar D Law
1
@TrafalgarDLaw J'ai publié une solution ci-dessus. - stackoverflow.com/a/44802256/3542883
Junior
22

Eh bien, rien de ce que j'ai utilisé n'a fonctionné, alors j'ai décidé de créer une véritable fonction de fractionnement simple, j'espère que cela aide:

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;
Jonathan
la source
18

Voici la fonction de fractionnement que j'utilise:

--
-- 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) ;
Olivier Delrieu
la source
Cela a bien fonctionné pour moi, et n'a pas provoqué une boucle infinie comme la réponse acceptée (pas clair pourquoi) - mais cela n'a pas fonctionné avec des espaces comme séparateur. Pour tous ceux qui tombent dessus, regardez plutôt stackoverflow.com/questions/2696884/… .
Max
15

Il n'y a pas de fonction de division de chaîne dans MySQL. vous devez donc créer votre propre fonction. Cela vous aidera. Plus de détails sur ce lien .

Fonction:

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

Usage:

SELECT SPLIT_STR(string, delimiter, position)

Exemple:

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

+-------+
| third |
+-------+
| ccc   |
+-------+
Rahul Chipad
la source
C'est la meilleure réponse à ce jour
Hydrocat
meilleure réponse, je l'utilise définitivement 👍✨
Rizki Noor Hidayat Wijaya
11

Vous pouvez également utiliser 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;
user2001117
la source
Cela a fonctionné pour moi. J'ai l'impression que c'est une mauvaise pratique, mais j'ai exécuté la même requête en dupliquant mon énoncé de cas et j'ai vu que cette approche est deux fois plus rapide. Merci.
jDub9
3
select (case when locate('(', LocationName) = 0 
        then 
            horse_name
        else 
           left(LocationName, locate('(', LocationName) - 1)
       end) as Country            
from   tblcountry;
Farookh Mansuri
la source
2

Pour obtenir le reste de la chaîne après la deuxième instance du délimiteur d'espace

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
Patnaidu Landa
la source
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; 

Expliquer:

Trouver le prénom et le nom sont faciles, il vous suffit d'utiliser la fonction SUBSTR_INDEX La magie se produit dans le nom intermédiaire, où a été utilisé SUBSTR avec Locate pour trouver la première position d'espace et la LONGUEUR du nom complet - (LENGTH prénom + LENGTH nom) pour obtenir tout le nom intermédiaire.

Notez que LENGTH du prénom et du nom ont été calculés à l'aide de SUBSTR_INDEX

Junior
la source
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
Paulo Roberto Rodrigues
la source
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.Exécutez cette fonction dans mysql. 2. cela créera une fonction. Vous pouvez maintenant utiliser cette fonction où vous le souhaitez.

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

3. Le premier paramètre getNameInitails ci-dessus est la chaîne que vous souhaitez filtrer et le second est le caractère spectateur sur lequel vous souhaitez séparer votre chaîne. 4. Dans l'exemple ci-dessus 'Kaleem Ul Hassan' est le nom et je veux obtenir les initiales et mon séparateur est l'espace ''.

user3867306
la source
1

Nous avons stocké la valeur du nom du cours et du nom du chapitre dans une seule colonne ChapterName.

Valeur stockée comme: "JAVA: Polymorphisme"

vous devez récupérer CourseName: JAVA et ChapterName: Polymorphism

Vous trouverez ci-dessous la requête de sélection SQL à récupérer.

       SELECT   
          SUBSTRING_INDEX(SUBSTRING_INDEX(ChapterName, ' ', 1), ' ', -1) AS 
       CourseName,

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

S'il vous plaît laissez-moi savoir si vous avez des questions à ce sujet.

Bikash Ranjan
la source
0

Pour obtenir le reste de la chaîne après la deuxième instance du délimiteur d'espace:

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
Web Biz
la source
0

Vous pouvez utiliser le common_schema et utiliser la tokenizefonction. Pour plus d'informations à ce sujet, suivez les liens. Votre code finirait comme:

call tokenize(name, ' ');

Cependant, sachez qu'un espace n'est pas un séparateur fiable pour le prénom et le nom. Par exemple, en Espagne, il est courant d'avoir deux noms de famille.

ToBe_HH
la source
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
Md. Obaidul Haque Sarker
la source
0

Créez d'abord la procédure comme ci-dessous:

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

Après cela, créez la procédure comme ci-dessous:

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

Comment appeler le test

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');
Pa Julieta
la source
0

Combiné quelques réponses ici pour créer un SP qui renvoie les parties de la chaîne.

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 ;
singhspk
la source