Eu tenho um campo de tabela membername
que contém o sobrenome e o nome dos usuários. É possível dividir aqueles em 2 campos memberfirst
, memberlast
?
Todos os registros têm este formato "Nome Sobrenome" (sem aspas e um espaço no meio).
Eu tenho um campo de tabela membername
que contém o sobrenome e o nome dos usuários. É possível dividir aqueles em 2 campos memberfirst
, memberlast
?
Todos os registros têm este formato "Nome Sobrenome" (sem aspas e um espaço no meio).
Respostas:
Infelizmente, o MySQL não possui uma função de string dividida. No entanto, você pode criar uma função definida pelo usuário para isso, como a descrita no seguinte artigo:
Com essa função:
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 ;
você poderia criar sua consulta da seguinte maneira:
SELECT SPLIT_STR(membername, ' ', 1) as memberfirst,
SPLIT_STR(membername, ' ', 2) as memberlast
FROM users;
Se você preferir não usar uma função definida pelo usuário e não considerar a consulta um pouco mais detalhada, também poderá fazer o seguinte:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(membername, ' ', 1), ' ', -1) as memberfirst,
SUBSTRING_INDEX(SUBSTRING_INDEX(membername, ' ', 2), ' ', -1) as memberlast
FROM users;
LENGTH
multibyte é seguro? "LENGTH (str): retorna o comprimento da string str, medida em bytes. Um caractere multibyte conta como vários bytes. Isso significa que, para uma string que contém cinco caracteres de 2 bytes, LENGTH () retorna 10, enquanto CHAR_LENGTH () retorna 5. "
Variante SELECT (não criando uma função definida pelo usuário):
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`;
Essa abordagem também cuida de:
A versão UPDATE seria:
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
);
Parece que as respostas existentes são mais complicadas ou não são uma resposta estrita à pergunta em particular.
Eu acho que a resposta simples é a seguinte consulta:
SELECT
SUBSTRING_INDEX(`membername`, ' ', 1) AS `memberfirst`,
SUBSTRING_INDEX(`membername`, ' ', -1) AS `memberlast`
;
Eu acho que não é necessário lidar com nomes com mais de duas palavras nessa situação específica. Se você deseja fazer isso corretamente, a divisão pode ser muito difícil ou até impossível em alguns casos:
Em um banco de dados projetado adequadamente, os nomes humanos devem ser armazenados em partes e no todo. Isso nem sempre é possível, é claro.
Se o seu plano é fazer isso como parte de uma consulta, por favor, não faça isso (a) . Sério, é um matador de desempenho. Pode haver situações em que você não se preocupa com o desempenho (como tarefas de migração pontuais para dividir os campos, permitindo melhor desempenho no futuro), mas, se você estiver fazendo isso regularmente para algo que não seja um banco de dados mickey-mouse, está desperdiçando recursos.
Se você alguma vez encontrar-se ter que processar apenas parte de uma coluna de alguma forma, seu projeto DB é falho. Pode funcionar bem em um catálogo de endereços residencial ou aplicativo de receitas ou em qualquer um dos inúmeros outros bancos de dados pequenos, mas não será escalável para sistemas "reais".
Armazene os componentes do nome em colunas separadas. É quase invariavelmente muito mais rápido juntar colunas com uma concatenação simples (quando você precisa do nome completo) do que separá-las com uma pesquisa de caracteres.
Se, por algum motivo, você não puder dividir o campo, insira pelo menos as colunas extras e use um gatilho de inserção / atualização para preenchê-las. Embora não seja o 3NF, isso garantirá que os dados ainda sejam consistentes e acelerará enormemente suas consultas. Você também pode garantir que as colunas extras sejam minúsculas (e indexadas se você estiver pesquisando nelas) ao mesmo tempo, para não ter que se preocupar com problemas de maiúsculas e minúsculas.
E, se você não pode nem adicionar as colunas e os gatilhos, esteja ciente (e informe seu cliente, se for para um cliente) de que não é escalável.
(a) Obviamente, se sua intenção é usar essa consulta para corrigir o esquema, para que os nomes sejam colocados em colunas separadas na tabela, e não na consulta, considero que é um uso válido. Mas reitero que fazê-lo na consulta não é realmente uma boa ideia.
usa isto
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX( `membername` , ' ', 2 ),' ',1) AS b,
SUBSTRING_INDEX(SUBSTRING_INDEX( `membername` , ' ', -1 ),' ',2) AS c FROM `users` WHERE `userid`='1'
Não exatamente respondendo à pergunta, mas diante do mesmo problema, acabei fazendo o seguinte:
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
No MySQL, está funcionando esta opção:
SELECT Substring(nameandsurname, 1, Locate(' ', nameandsurname) - 1) AS
firstname,
Substring(nameandsurname, Locate(' ', nameandsurname) + 1) AS lastname
FROM emp
O único caso em que você pode querer essa função é uma consulta UPDATE que alterará sua tabela para armazenar Nome e Sobrenome em campos separados.
O design do banco de dados deve seguir certas regras e a Normalização do Banco de Dados está entre as mais importantes
Eu tinha uma coluna onde o nome e o sobrenome estavam em uma coluna. O nome e o sobrenome foram separados por vírgula. O código abaixo funcionou. Não há verificação / correção de erro. Apenas uma divisão idiota. Utilizou o phpMyAdmin para executar a instrução SQL.
UPDATE tblAuthorList SET AuthorFirst = SUBSTRING_INDEX(AuthorLast,',',-1) , AuthorLast = SUBSTRING_INDEX(AuthorLast,',',1);
Isso pega smhg daqui e curt's from Last index de uma determinada substring no MySQL e os combina. Isso é para o mysql, tudo que eu precisava era obter uma divisão decente do nome para first_name last_name com o sobrenome uma única palavra, o primeiro nome tudo antes dessa palavra, onde o nome poderia ser nulo, 1 palavra, 2 palavras ou mais de 2 palavras. Ou seja: nulo; Maria; Mary Smith; Mary A. Smith; Mary Sue Ellen Smith;
Portanto, se nome for uma palavra ou nulo, last_name será nulo. Se o nome for> 1 palavra, last_name será a última palavra e first_name todas as palavras antes da última palavra.
Note que eu já aparei coisas como Joe Smith Jr.; Joe Smith Esq. e assim por diante, manualmente, o que foi doloroso, é claro, mas era pequeno o suficiente para fazer isso, então você deve ter certeza de observar realmente os dados no campo de nome antes de decidir qual método usar.
Observe que isso também apara o resultado, para que você não termine com espaços na frente ou após os nomes.
Só estou postando isso para outras pessoas que podem procurar no Google aqui o que eu precisava. Obviamente, isso funciona testando-o primeiro com o select.
É uma coisa única, então não me importo com eficiência.
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
)
);
O método que eu usei para dividir first_name em first_name e last_name quando os dados chegaram todos no campo first_name. Isso colocará apenas a última palavra no campo sobrenome; portanto, "john phillips sousa" será o nome "john phillips" e o sobrenome "sousa". Também evita a substituição de todos os registros que já foram corrigidos.
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
);