ฉันมีช่องตารางmembername
ซึ่งมีทั้งนามสกุลและชื่อผู้ใช้ มันเป็นไปได้ที่จะแยกเหล่านั้นลงใน 2 สาขาmemberfirst
, memberlast
?
ระเบียนทั้งหมดมีรูปแบบ "Firstname Lastname" (ไม่มีเครื่องหมายอัญประกาศและเว้นวรรค)
ฉันมีช่องตารางmembername
ซึ่งมีทั้งนามสกุลและชื่อผู้ใช้ มันเป็นไปได้ที่จะแยกเหล่านั้นลงใน 2 สาขาmemberfirst
, memberlast
?
ระเบียนทั้งหมดมีรูปแบบ "Firstname Lastname" (ไม่มีเครื่องหมายอัญประกาศและเว้นวรรค)
คำตอบ:
น่าเสียดายที่ 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 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 จะเป็น:
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 ซึ่งจะเปลี่ยนตารางของคุณเพื่อเก็บ Firstname และ Lastname ไว้ในฟิลด์แยกกัน
การออกแบบฐานข้อมูลต้องเป็นไปตามกฎเกณฑ์บางประการและการปรับมาตรฐานฐานข้อมูลเป็นหนึ่งในสิ่งที่สำคัญที่สุด
ฉันมีคอลัมน์ที่ชื่อและนามสกุลอยู่ในคอลัมน์เดียว ชื่อและนามสกุลถูกคั่นด้วยลูกน้ำ รหัสด้านล่างใช้งานได้ ไม่มีการตรวจสอบ / แก้ไขข้อผิดพลาด เพียงแค่แยกใบ้ ใช้ 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 จะเป็นโมฆะ ถ้าชื่อ> 1 คำ last_name คือคำสุดท้ายและ first_name ทุกคำก่อนคำสุดท้าย
โปรดทราบว่าฉันได้ตัดสิ่งต่างๆเช่น Joe Smith Jr. แล้ว โจสมิ ธ เอสไควร์ และอื่น ๆ ด้วยตนเองซึ่งแน่นอนว่าเจ็บปวด แต่ก็เล็กพอที่จะทำเช่นนั้นดังนั้นคุณต้องตรวจสอบให้แน่ใจว่าได้ดูข้อมูลในช่องชื่ออย่างแท้จริงก่อนที่จะตัดสินใจว่าจะใช้วิธีใด
โปรดทราบว่าสิ่งนี้จะตัดทอนผลลัพธ์ด้วยดังนั้นคุณจึงไม่ต้องเว้นวรรคหน้าหรือหลังชื่อ
ฉันแค่โพสต์สิ่งนี้สำหรับคนอื่น ๆ ที่อาจใช้ Google มาที่นี่เพื่อค้นหาสิ่งที่ฉันต้องการ วิธีนี้ได้ผลแน่นอนให้ทดสอบด้วยการเลือกก่อน
เป็นครั้งเดียวดังนั้นฉันไม่สนใจเรื่องประสิทธิภาพ
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>)