Разделить значение от одного поля до двух - PullRequest
115 голосов
/ 23 апреля 2010

У меня есть поле таблицы membername, которое содержит как фамилию, так и имя пользователя. Можно ли разделить их на 2 поля memberfirst, memberlast?

Все записи имеют этот формат «Имя, Фамилия» (без кавычек и пробела между ними). ​​

Ответы [ 13 ]

211 голосов
/ 23 апреля 2010

К сожалению, 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;
64 голосов
/ 26 сентября 2012

Вариант 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`;

Этот подход также учитывает:

  • имя члена значения без пробела : он добавит всю строку к memberfirst и установит memberlast в NULL.
  • membername значения, которые имеют несколько пробелов : он добавит все перед первым пробелом для memberfirst и оставшимся (включаяпробелы) до члена.

Версия ОБНОВЛЕНИЯ будет:

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
    );
20 голосов
/ 11 марта 2011

Если ваш план состоит в том, чтобы сделать это как часть запроса , , пожалуйста, не сделайте это (a) . Серьезно, это убийца производительности. Могут быть ситуации, когда вас не волнует производительность (например, одноразовые задания на миграцию для разделения полей, обеспечивающие более высокую производительность в будущем), но если вы делаете это регулярно для чего-либо, кроме базы данных mickey-mouse, вы Тратите ресурсы.

Если вы когда-либо обнаружите, что каким-то образом обрабатываете только часть столбца, ваш дизайн БД некорректен. Он вполне может хорошо работать с домашней адресной книгой, приложением рецептов или любой другой бесчисленной базой данных, но он не будет масштабируем для «реальных» систем.

Хранить компоненты имени в отдельных столбцах. Почти всегда гораздо быстрее объединить столбцы с помощью простой конкатенации (когда вам нужно полное имя), чем разделить их с помощью поиска символов.

Если по какой-либо причине вы не можете разделить поле, по крайней мере, вставьте дополнительные столбцы и используйте триггер вставки / обновления, чтобы заполнить их. Хотя это не 3NF, это гарантирует, что данные все еще согласованы, и значительно ускорит ваши запросы. Вы также можете убедиться, что дополнительные столбцы имеют нижний регистр (и индексируются, если вы ищете по ним) одновременно, чтобы не пришлось возиться с проблемами регистра.

И, если вы даже не можете добавить столбцы и триггеры, помните (и сообщите своему клиенту, если это для клиента), что он не масштабируется.


(a) Конечно, если вы намереваетесь использовать этот запрос для исправления схемы, чтобы имена помещались в отдельные столбцы в таблице вместо запроса , Я бы посчитал это правильным использованием. Но я повторяю, делать это в запросе не очень хорошая идея.

16 голосов
/ 27 сентября 2016

Кажется, что существующие ответы слишком сложны или не являются строгим ответом на конкретный вопрос.

Я думаю, простой ответ - следующий запрос:

SELECT
    SUBSTRING_INDEX(`membername`, ' ', 1) AS `memberfirst`,
    SUBSTRING_INDEX(`membername`, ' ', -1) AS `memberlast`
;

Я думаю, что в этой конкретной ситуации нет необходимости иметь дело с именами, превышающими два слова.Если вы хотите сделать это правильно, разделение может быть очень трудным или даже невозможным в некоторых случаях:

  • Эдгар Аллан По
  • Иоганн Вольфганг фонГете
  • Якоб Людвиг Феликс Мендельсон-Бартольди
  • Леа Мендельсон Бартольди
  • Петуфи Sándor
  • 黒 澤

В правильно спроектированной базе данных имена людей должны храниться как по частям, так и целиком.Конечно, это не всегда возможно.

7 голосов
/ 23 апреля 2010

используйте это

SELECT SUBSTRING_INDEX(SUBSTRING_INDEX( `membername` , ' ', 2 ),' ',1) AS b, 
SUBSTRING_INDEX(SUBSTRING_INDEX( `membername` , ' ', -1 ),' ',2) AS c FROM `users` WHERE `userid`='1'
5 голосов
/ 13 апреля 2012

Не совсем отвечаю на вопрос, но столкнулся с той же проблемой, и я закончил тем, что сделал:

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
3 голосов
/ 14 марта 2018

В MySQL работает эта опция:

SELECT Substring(nameandsurname, 1, Locate(' ', nameandsurname) - 1) AS 
       firstname, 
       Substring(nameandsurname, Locate(' ', nameandsurname) + 1)    AS lastname 
FROM   emp  
3 голосов
/ 23 апреля 2010

Единственный случай, когда вам может потребоваться такая функция, - это запрос UPDATE, который изменит вашу таблицу для хранения имени и фамилии в отдельных полях.

Дизайн базы данных должен соответствовать определенным правилам, а Нормализация базы данных является одним из наиболее важных

1 голос
/ 28 января 2016

Это берет smhg отсюда и curt's из Последний индекс данной подстроки в MySQL и объединяет их. Это для mysql, все, что мне нужно было получить приличное разделение имени на first_name last_name с фамилией, состоящей из одного слова, с именем перед всем этим единственным словом, где имя может быть нулевым, 1 словом, 2 словами или более 2 слов. Т.е.: ноль; Мэри; Мэри Смит; Мэри А. Смит; Мэри Сью Эллен Смит;

Так что, если имя - одно слово или ноль, last_name - ноль. Если имя -> 1 слово, last_name - последнее слово, а first_name - все слова перед последним словом.

Обратите внимание, что я уже обрезал такие вещи, как Джо Смит-младший; Джо Смит эсквайр и так далее, вручную, что, конечно, было болезненно, но для этого было достаточно мало, поэтому вы должны убедиться, что действительно посмотрите на данные в поле имени, прежде чем решить, какой метод использовать.

Обратите внимание, что это также обрезает результат, поэтому вы не получите пробелов перед или после имен.

Я просто публикую это для тех, кто может погуглить здесь в поисках того, что мне нужно. Это работает, конечно, сначала проверьте его с помощью выбора.

Это единовременная вещь, поэтому меня не волнует эффективность.

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
    ) 
);
1 голос
/ 01 февраля 2015

У меня был столбец, в котором имя и фамилия были в одном столбце.Имя и фамилия были разделены запятой.Код ниже работал.НЕТ проверки / исправления ошибок.Просто тупой раскол.Использовал phpMyAdmin для выполнения оператора SQL.

UPDATE tblAuthorList SET AuthorFirst = SUBSTRING_INDEX(AuthorLast,',',-1) , AuthorLast = SUBSTRING_INDEX(AuthorLast,',',1);

13.2.10 Синтаксис UPDATE

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...