2010-04-23 125 views
90

我有一個表字段membername,它包含用戶的姓氏和名字。是否有可能將這些分成兩個字段memberfirst,memberlast將字段拆分爲一個字段

所有的記錄都有這種格式的「名字姓氏」(沒有引號和中間的空格)。

+0

「所有記錄都有這種格式的」名字姓氏「(不帶引號和中間的空格)。」 ......奇蹟般......請**請**,在做數據庫決策時不要忘記像我這樣的人。我經常收到網站告訴我,我的姓氏包含一個*非法*(原文如此)的字符...... :( – 2016-06-02 18:53:26

+0

@StijndeWitt你是對的,但是看起來這個數據庫似乎不包含你的名字,至少不是在我的國家姓是先寫的,所以我也應該在這個數據表中「歧視」,看到這個 - > – 2018-02-07 15:55:25

回答

184

不幸的是,MySQL不具備分割字符串功能。然而,你可以創建一個user defined function這一點,如下面的文章中描述的:

與該功能:

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; 
+1

它再次出現:) – nomistic 2015-04-29 14:35:49

+0

這個問題的很好的解決方案! – Bergkamp 2015-05-11 12:49:07

+0

仍然不能將IN用作來自該分割操作的「數組值」? – Miguel 2016-09-08 15:39:58

4

,你可能希望這樣的功能的唯一情況是一個UPDATE查詢,它將改變你的表來存儲Firstname和Lastname到不同的字段。

數據庫設計必須遵循一定的規則,Database Normalization是最重要的中

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' 
+0

你能解釋一下嗎? – commonpike 2012-04-13 10:53:24

+0

這將從字段中獲取第一個和最後一個空格分隔的子字符串,這在任何情況下都不起作用。例如,如果姓名字段是「Lilly von Schtupp」,那麼您將得到'Lilly','Schtupp'作爲姓,姓。 – 2012-07-02 20:32:36

19

如果你的計劃是做到這一點的查詢的一部分,不要」 t那麼做(a)。嚴重的是,這是一個性能殺手。在某些情況下,您不關心性能(例如一次性遷移作業將字段拆分,以便將來可以獲得更好的性能),但是,如果您經常爲除米老鼠數據庫以外的任何其他目的執行此操作,則您浪費資源。

如果你有有史以來發現自己不得不以某種方式處理某一列的一部分,你的數據庫設計是有缺陷的。它可能適用於家庭地址簿或配方應用程序或任何其他小型數據庫,但它不會擴展到「真實」系統。

將名稱的組件存儲在單獨的列中。通過一個簡單的連接(當你需要全名時)連接字段幾乎總是快得多,而不是通過字符搜索將它們分開。

如果出於某種原因無法拆分字段,至少應放入額外的列並使用插入/更新觸發器來填充它們。雖然不是3NF,但這將保證數據仍然一致,並將大大加快查詢速度。您還可以確保額外的列在同一時間是較小的(並且如果您正在搜索它們,則編入索引),從而無需擺弄案件問題。

而且,如果您甚至無法添加列和觸發器,請注意(並且讓您的客戶端知道,如果它是針對客戶端的)它不可伸縮。


(一)當然,如果你的目的是使用該查詢修復架構,以便名字被放入單獨的列在而非查詢,我認爲這是一個有效的用途。但我重申,在查詢中這樣做並不是一個好主意。

+4

有時候,你必須這樣做。 F.E.我需要一個移植腳本,所以我不關心表演。 – 2013-11-05 11:13:10

+1

你甚至讀過這個問題嗎? – dfmiller 2014-09-11 16:17:12

+0

@dfmiller,是的,我做了,因此我的理由和詳細的迴應,並感謝您的興趣。如果你對我寫的東西有特定的問題,請指出,我會看看它是否可以改進。如果這確實是你的意圖,那麼你現在的評論對於改善情況幾乎沒有用處。或者,也許你只是在網上發佈隨機評論,很難說:-)我支持答案,當然,分欄訪問是不可擴展的,幾乎總是一個壞主意,除非它用於實際上是_fixing_分欄訪問。 – paxdiablo 2014-09-12 01:47:26

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 
47

如果你不想使用的功能,此查詢處理的事情比清潔其他答案:

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。
  • 成員名稱具有多個空格的值:它將在memberfirst的第一個空格和其餘部分(包括其他空格)之前向memberlast添加所有內容。

更新版本將是:

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 
    ); 
+0

哇!很好。謝謝。 – Pons 2013-03-27 22:42:55

+0

優秀。解決了我的問題。 – Aris 2014-01-14 15:04:06

+0

驚人! thankyou – 2015-10-20 05:42:04

-3

的MySQL 5.4提供了一個天然的分割功能:

SPLIT_STR(<column>, '<delimiter>', <index>) 
+1

您能否提供文檔鏈接? dev.mysql.com的搜索結果變幹了。 12.5節在這個功能的評論中確實有一個社區建議。 – DRaehal 2013-07-02 22:21:09

1

我有一列,其中第一和最後一個名字是兩人都在一列。名字和姓氏之間用逗號隔開。下面的代碼工作。沒有錯誤檢查/更正。只是一個愚蠢的分裂。使用phpMyAdmin來執行SQL語句。

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

13.2.10 UPDATE Syntax

1

這需要從這裏生硬的smhg從Last index of a given substring in MySQL,並結合他們。這是用於mysql的,我所需要的只是將姓氏的名稱拆分爲first_name last_name,姓氏單個單詞,第一個名稱在單個單詞之前,名稱可以爲null,1個單詞,2個單詞或超過2個字。即:空;瑪麗;瑪麗史密斯;瑪麗A.史密斯;瑪麗蘇埃倫史密斯;

因此,如果名稱是一個單詞或null,則last_name爲空。如果名字大於1個單詞,則last_name是最後一個單詞,first_name是最後一個單詞之前的所有單詞。

請注意,我已經削減了像喬史密斯這樣的東西;喬史密斯Esq。等等,手動,這當然是痛苦的,但它足夠小,所以你想在確定使用哪種方法之前確保真正查看名稱字段中的數據。

請注意,這也會削減結果,所以您不會在名稱前面或後面出現空格。

我只是發佈此爲其他人可能谷歌他們的方式在這裏尋找我需要什麼。這當然有效,首先用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 
    ) 
); 
0

方法我用於在first_name字段中的數據全部到達時將first_name拆分爲first_name和last_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 
6

似乎現有的答案是過於複雜或不是對特定問題的嚴格答案。

我認爲,答案很簡單,下面的查詢:

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

我認爲這是沒有必要應對這種特殊情況下更比雙字名。如果你想要做正確的,拆分可以在某些情況下是非常困難甚至是不可能的:

  • 埃德加·愛倫·
  • 約翰·沃爾夫岡·馮·歌德
  • 雅各布·路德維希·費利克斯門德爾鬆·巴托爾迪
  • LEA 門德爾鬆
  • Pe的TOFI的Sándor
  • 黒澤

在設計合理的數據庫,人的名字應該被同時存儲在零部件和整體。當然,這並非總是可行的。

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 
    ); 
相關問題