У меня есть поле таблицы, membername
которое содержит как фамилии, так и имена пользователей. Можно ли разделить эти в 2 -х полей memberfirst
, memberlast
?
Все записи имеют формат «Имя Фамилия» (без кавычек и пробелов между ними).
У меня есть поле таблицы, membername
которое содержит как фамилии, так и имена пользователей. Можно ли разделить эти в 2 -х полей memberfirst
, memberlast
?
Все записи имеют формат «Имя Фамилия» (без кавычек и пробелов между ними).
Ответы:
К сожалению, MySQL не поддерживает функцию разделения строк. Однако вы можете создать для этого пользовательскую функцию , например, описанную в следующей статье:
С этой функцией:
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 ;
вы могли бы построить свой запрос следующим образом:
SELECT SPLIT_STR(membername, ' ', 1) as memberfirst,
SPLIT_STR(membername, ' ', 2) as memberlast
FROM users;
Если вы предпочитаете не использовать пользовательскую функцию и не возражаете, чтобы запрос был более подробным, вы также можете сделать следующее:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(membername, ' ', 1), ' ', -1) as memberfirst,
SUBSTRING_INDEX(SUBSTRING_INDEX(membername, ' ', 2), ' ', -1) as memberlast
FROM users;
LENGTH
Безопасно ли ваше использование многобайтовых файлов ? "LENGTH (str): возвращает длину строки str, измеренную в байтах. Многобайтовый символ считается как несколько байтов. Это означает, что для строки, содержащей пять 2-байтовых символов, LENGTH () возвращает 10, тогда как CHAR_LENGTH () возвращает 5.»
Вариант SELECT (без создания пользовательской функции):
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`;
Этот подход также учитывает:
Версия ОБНОВЛЕНИЯ будет:
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
);
Кажется, что существующие ответы слишком сложны или не являются строгим ответом на конкретный вопрос.
Думаю, простой ответ - следующий запрос:
SELECT
SUBSTRING_INDEX(`membername`, ' ', 1) AS `memberfirst`,
SUBSTRING_INDEX(`membername`, ' ', -1) AS `memberlast`
;
Я думаю, что в данной конкретной ситуации нет необходимости иметь дело с именами, состоящими из более чем двух слов. Если вы хотите сделать это правильно, разделение может быть очень сложным или даже невозможным в некоторых случаях:
В правильно спроектированной базе данных человеческие имена должны храниться как по частям, так и целиком. Конечно, это не всегда возможно.
Если ваш план должен сделать это как часть запроса, пожалуйста , не делать (а) . Серьезно, это убийца производительности. Могут быть ситуации, когда вас не заботит производительность (например, одноразовые задания по миграции для разделения полей, позволяющие повысить производительность в будущем), но, если вы делаете это регулярно для чего-либо, кроме базы данных микки-мауса, вы зря тратим ресурсы.
Если вы когда-нибудь обнаружите, что каким-то образом обрабатываете только часть столбца, ваша БД имеет изъян. Он вполне может нормально работать с домашней адресной книгой или приложением рецептов или с любой из множества других небольших баз данных, но он не будет масштабироваться до «реальных» систем.
Храните компоненты имени в отдельных столбцах. Почти всегда гораздо быстрее объединить столбцы с помощью простой конкатенации (когда вам нужно полное имя), чем разделить их с помощью поиска по символам.
Если по какой-либо причине вы не можете разделить поле, по крайней мере, добавьте дополнительные столбцы и используйте триггер вставки / обновления для их заполнения. Хотя это и не 3NF, это гарантирует, что данные по-прежнему согласованы, и значительно ускорит ваши запросы. Вы также можете убедиться, что дополнительные столбцы имеют нижний регистр (и индексируются, если вы выполняете поиск по ним) одновременно, чтобы вам не приходилось возиться с проблемами с регистром.
И, если вы даже не можете добавить столбцы и триггеры, имейте в виду (и сообщите своему клиенту, если это для клиента), что он не масштабируется.
(a) Конечно, если вы намерены использовать этот запрос для исправления схемы, чтобы имена помещались в отдельные столбцы в таблице, а не в запросе, я бы счел это допустимым использованием. Но я повторяю, делать это в запросе - не самая лучшая идея.
использовать это
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX( `membername` , ' ', 2 ),' ',1) AS b,
SUBSTRING_INDEX(SUBSTRING_INDEX( `membername` , ' ', -1 ),' ',2) AS c FROM `users` WHERE `userid`='1'
Не совсем отвечая на вопрос, но столкнувшись с той же проблемой, я сделал это:
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
В MySQL работает эта опция:
SELECT Substring(nameandsurname, 1, Locate(' ', nameandsurname) - 1) AS
firstname,
Substring(nameandsurname, Locate(' ', nameandsurname) + 1) AS lastname
FROM emp
Единственный случай, когда вам может понадобиться такая функция, - это запрос UPDATE, который изменит вашу таблицу, чтобы сохранить имя и фамилию в отдельных полях.
Дизайн базы данных должен соответствовать определенным правилам, и нормализация базы данных является одним из наиболее важных.
У меня был столбец, в котором имя и фамилия были в одном столбце. Имя и фамилия разделялись запятой. Код ниже работал. НЕТ проверки / исправления ошибок. Просто тупой раскол. Использовал phpMyAdmin для выполнения инструкции SQL.
UPDATE tblAuthorList SET AuthorFirst = SUBSTRING_INDEX(AuthorLast,',',-1) , AuthorLast = SUBSTRING_INDEX(AuthorLast,',',1);
Это берет smhg отсюда и curt из последнего индекса данной подстроки в MySQL и объединяет их. Это для mysql, все, что мне нужно, это получить приличное разделение имени на first_name last_name с фамилией одним словом, первым именем перед этим единственным словом, где имя может быть нулевым, 1 словом, 2 словами или более 2 слов. Т.е.: Null; Мэри; Мэри Смит; Мэри А. Смит; Мэри Сью Эллен Смит;
Итак, если name состоит из одного слова или null, last_name имеет значение null. Если name> 1 слова, last_name - это последнее слово, а first_name - все слова перед последним словом.
Обратите внимание, что я уже обрезал такие вещи, как Джо Смит младший; Джо Смит эсквайр. и так далее, вручную, что, конечно, было болезненно, но для этого было достаточно мало, поэтому вы хотите убедиться, что действительно посмотрите на данные в поле имени, прежде чем решить, какой метод использовать.
Обратите внимание, что это также обрезает результат, поэтому вы не останетесь без пробелов перед или после имен.
Я просто отправляю это для других, которые могут найти в Google то, что мне нужно. Это, конечно, работает, сначала проверьте его с помощью select.
Это одноразовая вещь, поэтому меня не волнует эффективность.
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
)
);
Метод, который я использовал для разделения first_name на first_name и last_name, когда все данные поступали в поле first_name. Это поместит только последнее слово в поле фамилии, поэтому «john phillips sousa» будет именем «john phillips» и фамилией «sousa». Это также позволяет избежать перезаписи любых уже исправленных записей.
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
);
mysql 5.4 предоставляет встроенную функцию разделения:
SPLIT_STR(<column>, '<delimiter>', <index>)