将值从一个字段拆分为两个

tsi*_*ger 120 mysql split

我有一个表字段membername,其中包含姓氏和用户的名字.是否有可能分裂成那些2场memberfirst,memberlast

所有记录都具有"Firstname Lastname"格式(没有引号,中间有空格).

Dan*_*llo 221

不幸的是,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 ;
Run Code Online (Sandbox Code Playgroud)

您可以按如下方式构建查询:

SELECT SPLIT_STR(membername, ' ', 1) as memberfirst,
       SPLIT_STR(membername, ' ', 2) as memberlast
FROM   users;
Run Code Online (Sandbox Code Playgroud)

如果您不想使用用户定义的函数,并且您不介意查询更冗长,您还可以执行以下操作:

SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(membername, ' ', 1), ' ', -1) as memberfirst,
       SUBSTRING_INDEX(SUBSTRING_INDEX(membername, ' ', 2), ' ', -1) as memberlast
FROM   users;
Run Code Online (Sandbox Code Playgroud)

  • 你使用`LENGTH`多字节是否安全?"LENGTH(str):返回字符串str的长度,以字节为单位.多字节字符计为多个字节.这意味着对于包含五个2字节字符的字符串,LENGTH()返回10,而CHAR_LENGTH()返回5." (3认同)
  • 它再次出现:) (2认同)

smh*_*mhg 67

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`;
Run Code Online (Sandbox Code Playgroud)

这种方法也需要注意:

  • 成员名称值没有空格:它会增加整个字符串memberfirst并设置memberlast为NULL.
  • 具有多个空格的 membername :它会将第一个空格之前的所有内容添加到memberfirst,将余数(包括其他空格)添加到memberlast.

UPDATE版本将是:

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
    );
Run Code Online (Sandbox Code Playgroud)


pax*_*blo 20

如果您的计划是作为查询的一部分执行此操作,要这样做(a).说真的,这是一个性能杀手.在某些情况下,您可能不关心性能(例如一次性迁移作业以分割字段以便将来获得更好的性能)但是,如果您经常对除米老鼠数据库之外的任何其他内容执行此操作,则'浪费资源.

如果你曾经发现自己有处理一列中的一部分以某种方式,你的数据库的设计是有缺陷的.它可能适用于家庭地址簿或食谱应用程序或任何其他无数小型数据库,但它不能扩展到"真实"系统.

将名称的组件存储在单独的列中.通过简单的连接(当您需要全名)将列与一个字符搜索分开时,将列连接起来几乎总是快得多.

如果由于某种原因你无法拆分字段,至少放入额外的列并使用插入/更新触发器来填充它们.虽然不是3NF,但这将保证数据仍然一致,并将大大加快您的查询速度.您还可以确保额外的列是低层的(并且如果您正在搜索它们,则会编入索引),以便不必处理案例问题.

而且,如果您甚至无法添加列和触发器,请注意(并让您的客户端知道,如果是客户端),它是不可扩展的.


(一)当然,如果你的目的是使用此查询到固定的模式,这样的名字被放入单独的列在表中,而不是查询,我认为这是一个有效的使用.但我重申,在查询中这样做并不是一个好主意.

  • 有时,你必须这样做.我需要在迁移脚本中使用它,所以我不关心表演. (4认同)
  • 问题是如何将单个列拆分为2,然后通过说"不要那样"进行回答,然后继续解释为什么要拆分它们.你的第一段听起来像是赞成或将它们保持为一列,但其他段落则相反. (3认同)

Dáv*_*áth 18

现有的回答似乎过于复杂,或者对特定问题没有严格的回答.

我想,简单的答案是以下查询:

SELECT
    SUBSTRING_INDEX(`membername`, ' ', 1) AS `memberfirst`,
    SUBSTRING_INDEX(`membername`, ' ', -1) AS `memberlast`
;
Run Code Online (Sandbox Code Playgroud)

我认为在这种特殊情况下没有必要处理超过两个字的名字.如果你想正确地做到这一点,在某些情况下拆分可能非常困难甚至是不可能的:

  • 埃德加爱伦坡
  • 约翰沃尔夫冈冯歌德
  • Jakob Ludwig Felix Mendelssohn-Bartholdy
  • Lea Mendelssohn Bartholdy
  • 裴多菲的Sándor
  • 泽黒:明

在设计合理的数据库中,人名应该存储在部分和整体中.当然,这并非总是可行的.


Kar*_*hik 7

用这个

SELECT SUBSTRING_INDEX(SUBSTRING_INDEX( `membername` , ' ', 2 ),' ',1) AS b, 
SUBSTRING_INDEX(SUBSTRING_INDEX( `membername` , ' ', -1 ),' ',2) AS c FROM `users` WHERE `userid`='1'
Run Code Online (Sandbox Code Playgroud)


小智 6

在 MySQL 中,这是使用此选项:

SELECT Substring(nameandsurname, 1, Locate(' ', nameandsurname) - 1) AS 
       firstname, 
       Substring(nameandsurname, Locate(' ', nameandsurname) + 1)    AS lastname 
FROM   emp  
Run Code Online (Sandbox Code Playgroud)


com*_*ike 5

不完全回答这个问题,但面对同样的问题,我最终做到了这一点:

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
Run Code Online (Sandbox Code Playgroud)