Ho un campo tabella membernameche contiene sia il cognome che il nome degli utenti. E 'possibile dividere quelli in 2 campi memberfirst, memberlast?
Tutti i record hanno questo formato "Nome Cognome" (senza virgolette e uno spazio in mezzo).
Ho un campo tabella membernameche contiene sia il cognome che il nome degli utenti. E 'possibile dividere quelli in 2 campi memberfirst, memberlast?
Tutti i record hanno questo formato "Nome Cognome" (senza virgolette e uno spazio in mezzo).
Risposte:
Purtroppo MySQL non dispone di una funzione di stringa divisa. Tuttavia, è possibile creare una funzione definita dall'utente per questo, come quella descritta nel seguente articolo:
Con quella funzione:
DELIMITER $$
CREATE FUNCTION SPLIT_STR(
x VARCHAR(255),
delim VARCHAR(12),
pos INT
)
RETURNS VARCHAR(255) DETERMINISTIC
BEGIN
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
delim, '');
END$$
DELIMITER ;
sarai in grado di creare la tua query come segue:
SELECT SPLIT_STR(membername, ' ', 1) as memberfirst,
SPLIT_STR(membername, ' ', 2) as memberlast
FROM users;
Se preferisci non utilizzare una funzione definita dall'utente e non ti dispiace che la query sia un po 'più dettagliata, puoi anche fare quanto segue:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(membername, ' ', 1), ' ', -1) as memberfirst,
SUBSTRING_INDEX(SUBSTRING_INDEX(membername, ' ', 2), ' ', -1) as memberlast
FROM users;
LENGTHmultibyte è sicuro? "LENGTH (str): restituisce la lunghezza della stringa str, misurata in byte. Un carattere multibyte conta come byte multipli. Ciò significa che per una stringa contenente cinque caratteri a 2 byte, LENGTH () restituisce 10, mentre CHAR_LENGTH () restituisce 5."
Variante SELECT (non creazione di una funzione definita dall'utente):
SELECT IF(
LOCATE(' ', `membername`) > 0,
SUBSTRING(`membername`, 1, LOCATE(' ', `membername`) - 1),
`membername`
) AS memberfirst,
IF(
LOCATE(' ', `membername`) > 0,
SUBSTRING(`membername`, LOCATE(' ', `membername`) + 1),
NULL
) AS memberlast
FROM `user`;
Questo approccio si occupa anche di:
La versione di AGGIORNAMENTO sarebbe:
UPDATE `user` SET
`memberfirst` = IF(
LOCATE(' ', `membername`) > 0,
SUBSTRING(`membername`, 1, LOCATE(' ', `membername`) - 1),
`membername`
),
`memberlast` = IF(
LOCATE(' ', `membername`) > 0,
SUBSTRING(`membername`, LOCATE(' ', `membername`) + 1),
NULL
);
Sembra che le risposte esistenti siano troppo complicate o non una risposta rigorosa alla domanda specifica.
Penso che la semplice risposta sia la seguente domanda:
SELECT
SUBSTRING_INDEX(`membername`, ' ', 1) AS `memberfirst`,
SUBSTRING_INDEX(`membername`, ' ', -1) AS `memberlast`
;
Penso che non sia necessario trattare nomi con più di due parole in questa particolare situazione. Se vuoi farlo correttamente, dividere può essere molto difficile o addirittura impossibile in alcuni casi:
In un database progettato correttamente, i nomi umani devono essere memorizzati sia in parti che nel loro insieme. Questo non è sempre possibile, ovviamente.
Se il tuo piano è di farlo come parte di una query, ti preghiamo di non farlo (a) . Seriamente, è un killer delle prestazioni. Potrebbero verificarsi situazioni in cui non ti interessano le prestazioni (come i processi di migrazione una tantum per dividere i campi consentendo prestazioni migliori in futuro) ma, se lo fai regolarmente per qualsiasi cosa diversa da un database di topolino, tu stai sprecando risorse.
Se ti capita mai di dover elaborare solo una parte di una colonna in qualche modo, la progettazione del tuo DB è difettosa. Potrebbe funzionare bene su una rubrica di casa o su un'applicazione ricetta o su una miriade di altri piccoli database ma non sarà scalabile su sistemi "reali".
Conservare i componenti del nome in colonne separate. È quasi sempre molto più veloce unire le colonne con una semplice concatenazione (quando è necessario il nome completo) piuttosto che dividerle con una ricerca di caratteri.
Se, per qualche motivo, non è possibile dividere il campo, inserire almeno le colonne aggiuntive e utilizzare un trigger di inserimento / aggiornamento per popolarle. Sebbene non sia 3NF, questo garantirà che i dati siano ancora coerenti e accelererà enormemente le tue query. Puoi anche assicurarti che le colonne extra siano maiuscole (e indicizzate se le stai cercando) allo stesso tempo in modo da non dover giocherellare con i problemi del caso.
E, se non riesci nemmeno ad aggiungere le colonne e i trigger, fai attenzione (e rendi consapevole il tuo client, se è per un client) che non è scalabile.
(a) Ovviamente, se il tuo intento è quello di utilizzare questa query per correggere lo schema in modo che i nomi siano collocati in colonne separate nella tabella anziché nella query, lo considererei un uso valido. Ma lo ribadisco, farlo nella query non è davvero una buona idea.
Usa questo
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX( `membername` , ' ', 2 ),' ',1) AS b,
SUBSTRING_INDEX(SUBSTRING_INDEX( `membername` , ' ', -1 ),' ',2) AS c FROM `users` WHERE `userid`='1'
Non rispondendo esattamente alla domanda, ma di fronte allo stesso problema ho finito per fare questo:
UPDATE people_exit SET last_name = SUBSTRING_INDEX(fullname,' ',-1)
UPDATE people_exit SET middle_name = TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(fullname,last_name,1),' ',-2))
UPDATE people_exit SET middle_name = '' WHERE CHAR_LENGTH(middle_name)>3
UPDATE people_exit SET first_name = SUBSTRING_INDEX(fullname,concat(middle_name,' ',last_name),1)
UPDATE people_exit SET first_name = middle_name WHERE first_name = ''
UPDATE people_exit SET middle_name = '' WHERE first_name = middle_name
In MySQL funziona questa opzione:
SELECT Substring(nameandsurname, 1, Locate(' ', nameandsurname) - 1) AS
firstname,
Substring(nameandsurname, Locate(' ', nameandsurname) + 1) AS lastname
FROM emp
L'unico caso in cui potresti desiderare una tale funzione è una query UPDATE che modificherà la tua tabella per archiviare Nome e Cognome in campi separati.
La progettazione del database deve seguire alcune regole e la normalizzazione del database è tra le più importanti
Avevo una colonna in cui il nome e il cognome erano entrambi in una colonna. Il nome e il cognome erano separati da una virgola. Il codice seguente ha funzionato. Non ci sono errori di controllo / correzione. Solo una stupida spaccatura. Usato phpMyAdmin per eseguire l'istruzione SQL.
UPDATE tblAuthorList SET AuthorFirst = SUBSTRING_INDEX(AuthorLast,',',-1) , AuthorLast = SUBSTRING_INDEX(AuthorLast,',',1);
Questo prende smhg da qui e bruscamente dall'ultimo indice di una determinata sottostringa in MySQL e li combina. Questo è per mysql, tutto ciò di cui avevo bisogno era ottenere una discreta suddivisione del nome in first_name last_name con il cognome una sola parola, il nome tutto prima di quella singola parola, dove il nome poteva essere nullo, 1 parola, 2 parole o più di 2 parole. Vale a dire: null; Maria; Mary Smith; Mary A. Smith; Mary Sue Ellen Smith;
Quindi, se name è una parola o null, last_name è null. Se il nome è> 1 parola, last_name è l'ultima parola e first_name tutte le parole prima dell'ultima parola.
Nota che ho già eliminato cose come Joe Smith Jr.; Joe Smith Esq. e così via, manualmente, il che è stato doloroso, ovviamente, ma era abbastanza piccolo per farlo, quindi vuoi assicurarti di guardare davvero i dati nel campo del nome prima di decidere quale metodo usare.
Si noti che questo riduce anche il risultato, quindi non si finisce con spazi davanti o dopo i nomi.
Sto solo pubblicando questo per gli altri che potrebbero andare su Google a cercare ciò di cui avevo bisogno. Questo funziona, ovviamente, testalo prima con il select.
È una cosa sola, quindi non mi interessa l'efficienza.
SELECT TRIM(
IF(
LOCATE(' ', `name`) > 0,
LEFT(`name`, LENGTH(`name`) - LOCATE(' ', REVERSE(`name`))),
`name`
)
) AS first_name,
TRIM(
IF(
LOCATE(' ', `name`) > 0,
SUBSTRING_INDEX(`name`, ' ', -1) ,
NULL
)
) AS last_name
FROM `users`;
UPDATE `users` SET
`first_name` = TRIM(
IF(
LOCATE(' ', `name`) > 0,
LEFT(`name`, LENGTH(`name`) - LOCATE(' ', REVERSE(`name`))),
`name`
)
),
`last_name` = TRIM(
IF(
LOCATE(' ', `name`) > 0,
SUBSTRING_INDEX(`name`, ' ', -1) ,
NULL
)
);
Metodo che ho usato per dividere first_name in first_name e last_name quando i dati sono arrivati tutti nel campo first_name. Questo metterà solo l'ultima parola nel campo del cognome, quindi "john phillips sousa" sarà il nome "john phillips" e il cognome "sousa". Evita inoltre di sovrascrivere tutti i record che sono già stati corretti.
set last_name=trim(SUBSTRING_INDEX(first_name, ' ', -1)), first_name=trim(SUBSTRING(first_name,1,length(first_name) - length(SUBSTRING_INDEX(first_name, ' ', -1)))) where list_id='$List_ID' and length(first_name)>0 and length(trim(last_name))=0
UPDATE `salary_generation_tbl` SET
`modified_by` = IF(
LOCATE('$', `other_salary_string`) > 0,
SUBSTRING(`other_salary_string`, 1, LOCATE('$', `other_salary_string`) - 1),
`other_salary_string`
),
`other_salary` = IF(
LOCATE('$', `other_salary_string`) > 0,
SUBSTRING(`other_salary_string`, LOCATE('$', `other_salary_string`) + 1),
NULL
);