एक क्षेत्र से दो में विभाजित मूल्य


125

मुझे एक टेबल फ़ील्ड मिली है membernameजिसमें अंतिम नाम और उपयोगकर्ताओं का पहला नाम दोनों हैं। यह संभव 2 क्षेत्रों में विभाजित करने के लिए उन है memberfirst, memberlast?

सभी अभिलेखों में यह प्रारूप "फर्स्टनाम लास्टनाम" (बिना उद्धरण और बीच में एक स्थान) है।


6
"सभी रिकॉर्ड में यह प्रारूप है" Firstname Lastname "(बिना उद्धरण और बीच में एक स्थान)।" ... चमत्कारिक ढंग से ... कृपया, कृपया , मेरे जैसे लोगों के बारे में मत भूलो जब डेटाबेस निर्णय ले रहे हैं। बहुत बार मुझे ऐसी वेबसाइटें मिलती हैं जो मुझे बताती हैं कि मेरा अंतिम नाम एक गैरकानूनी (सिक) चरित्र है: ...(
Stijn de Witt

@StijndeWitt आप सामान्य रूप से सही हैं, हालांकि ऐसा लगता है कि इस डेटाबेस में आपका नाम नहीं है, कम से कम इसके आधिकारिक रूप में नहीं। मेरे देश में उपनाम पहले लिखे गए हैं, इसलिए मैं इस डेटा तालिका में "भेदभाव" भी करता हूं। बस इसे देखें ->
दाविद होर्वाथ

जवाबों:


226

दुर्भाग्य से 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;

इस समस्या के लिए महान समाधान!
बर्गकैम्प

अभी भी आप उस विभाजन ऑपरेशन से "मूल्यों की एक सरणी" के रूप में IN का उपयोग नहीं कर सकते हैं?
मिगुएल

3
क्या आपका LENGTHमल्टीबाइट का उपयोग सुरक्षित है? "LENGTH (str): स्ट्रिंग बाइट की लंबाई लौटाता है, जिसे बाइट्स में मापा जाता है। एक मल्टीबाइट कैरेक्टर मल्टीपल बाइट्स के रूप में गिना जाता है। इसका मतलब है कि स्ट्रिंग में 2-बाइट वाले वर्णों के लिए, LENGTH () 10 देता है, जबकि CHAR_LENGTH () रिटर्न करता है। 5. "
Erk

मल्टीबाइट / utf8 वर्णों के साथ काम करते समय यह ठीक से काम नहीं करेगा, जैसा कि @Erk ने उल्लेख किया है। केवल दो SUBSTRING_INDEX बयानों के साथ सरल उपाय UTF8 / multibyte साथ काम करता है
माइकल

LENGTH (), LOCATE () या ऐसी कोई भी चीज़ जो किसी पद गणना पर निर्भर करती है, मल्टीबाइट वर्णों के साथ विफल हो जाएगी।
माइकल

68

चयनित संस्करण (उपयोगकर्ता परिभाषित फ़ंक्शन नहीं बना रहा है):

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`;

यह दृष्टिकोण भी ध्यान रखता है:

  • सदस्यनाम एक स्थान के बिना मान : यह पूरे स्ट्रिंग को मेसफेयर में जोड़ेगा और सदस्य को NULL में सेट करेगा।
  • सदस्यनाम मान जिसमें कई स्थान हैं : यह पहले स्थान से पहले सब कुछ जोड़ देगा और शेष (अतिरिक्त रिक्त स्थान सहित) सदस्य को।

अद्यतन संस्करण होगा:

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

यह भी उपयोगी होगा कि अंतिम नाम के लिए सिर्फ अंतिम शब्द को कैसे काटें, और पहले नाम के लिए सभी गैर अंतिम, उदाहरण के लिए: मैरी ए। स्मिथ जो एक प्रकार से मुझे एक पुरानी डीबी तालिका में इससे निपटना है ठीक कर। मैं देखूंगा कि क्या मैं इसका पता लगा सकता हूं और परिणाम पोस्ट कर सकता हूं, यदि नहीं, तो आप उस विकल्प को भी पोस्ट कर सकते हैं जो आपका उत्तर पूरा कर देगा।
छिपकली

हम इसे पूर्णांक में कैसे डाल सकते हैं क्योंकि सदस्य नामचर्चा है .. सदस्य को टाइप इंट का होना चाहिए। क्या यह काम करेगा अगर मैं सीधे कास्ट () का उपयोग करूं?
अनंतनामा

आप सर मेडल के लायक हैं।
rpajaziti

23

ऐसा लगता है कि मौजूदा प्रतिक्रियाएं जटिल हैं या विशेष प्रश्न का कोई सख्त जवाब नहीं है।

मुझे लगता है, सरल उत्तर निम्नलिखित प्रश्न है:

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

मुझे लगता है कि इस विशेष स्थिति में दो से अधिक शब्दों के नामों से निपटने के लिए आवश्यक नहीं है। यदि आप इसे ठीक से करना चाहते हैं, तो कुछ मामलों में विभाजन बहुत कठिन या असंभव भी हो सकता है:

  • जोहान सेबेस्टियन बाख
  • जोहान वोल्फगैंग वॉन गोएथे
  • एडगर एलन पो
  • जैकब लुडविग फेलिक्स मेंडेलसोहन-बार्थोल्डी
  • पेटीफी सोंडोर
  • 澤黒

ठीक से डिज़ाइन किए गए डेटाबेस में, मानव नाम को भागों और संपूर्ण दोनों में संग्रहीत किया जाना चाहिए। यह हमेशा संभव नहीं है, निश्चित रूप से।


20

यदि आपकी योजना क्वेरी के हिस्से के रूप में ऐसा करने की है , तो कृपया ऐसा न करें (a) । गंभीरता से, यह एक प्रदर्शन हत्यारा है। ऐसी स्थितियाँ हो सकती हैं जहाँ आपको प्रदर्शन की परवाह नहीं है (जैसे कि भविष्य में बेहतर प्रदर्शन की अनुमति देने वाले क्षेत्रों को विभाजित करने के लिए वन-ऑफ माइग्रेशन जॉब) लेकिन, अगर आप नियमित रूप से मिकी-माउस डेटाबेस के अलावा किसी अन्य चीज़ के लिए ऐसा कर रहे हैं, तो आप संसाधनों को बर्बाद कर रहे हैं।

यदि आप कभी भी अपने आप को किसी तरह से एक कॉलम के केवल एक भाग को संसाधित करने के लिए पाते हैं, तो आपका डीबी डिज़ाइन त्रुटिपूर्ण है। यह अच्छी तरह से एक घर का पता पुस्तिका या नुस्खा आवेदन या असंख्य अन्य छोटे डेटाबेस पर ठीक काम कर सकता है, लेकिन यह "वास्तविक" सिस्टम के लिए स्केलेबल नहीं होगा।

नाम के घटकों को अलग कॉलम में संग्रहीत करें। स्तंभों में शामिल होने के लिए एक साधारण संयोजन (जब आपको पूर्ण नाम की आवश्यकता होती है) की तुलना में यह लगभग बहुत अधिक तेज है, एक चरित्र खोज के साथ उन्हें अलग करना है।

यदि, किसी कारण से आप फ़ील्ड को विभाजित नहीं कर सकते हैं, तो कम से कम अतिरिक्त कॉलम में डालें और उन्हें पॉप्युलेट करने के लिए एक इन्सर्ट / अपडेट ट्रिगर का उपयोग करें। जबकि 3NF नहीं, यह गारंटी देगा कि डेटा अभी भी सुसंगत है और आपके प्रश्नों को बड़े पैमाने पर गति देगा। आप यह भी सुनिश्चित कर सकते हैं कि अतिरिक्त कॉलम कम-केस किए गए हैं (और यदि आप उन पर खोज कर रहे हैं तो अनुक्रमित हैं) तो मामले के मुद्दों के साथ चारों ओर नहीं करना है।

और, यदि आप कॉलम और ट्रिगर्स भी नहीं जोड़ सकते हैं, तो जागरूक रहें (और अपने क्लाइंट को अवगत कराएं, यदि यह क्लाइंट के लिए है) तो यह स्केलेबल नहीं है।


(ए) बेशक, अगर आपका इरादा स्कीमा को ठीक करने के लिए इस क्वेरी का उपयोग करने का है ताकि नामों को क्वेरी के बजाय तालिका में अलग-अलग कॉलम में रखा जाए , तो मैं समझता हूं कि यह एक वैध उपयोग है। लेकिन मैं दोहराता हूं, क्वेरी में ऐसा करना वास्तव में एक अच्छा विचार नहीं है।


4
कभी-कभी, आपको यह करना होगा। Fe मुझे माइग्रेशन स्क्रिप्ट में इसकी आवश्यकता है, इसलिए मुझे प्रदर्शनों की परवाह नहीं है।
मैथ्यू नेपोलि

@ पीडीएफमिलर, हां, मैंने किया, इसलिए मेरी तर्कपूर्ण और विस्तृत प्रतिक्रिया, और आपकी रुचि के लिए धन्यवाद। यदि आपके पास मेरे द्वारा लिखी गई किसी चीज़ का कोई विशिष्ट मुद्दा है, तो उसे इंगित करें और मैं देखूंगा कि क्या इसमें सुधार किया जा सकता है। आपकी वर्तमान टिप्पणी स्थिति को सुधारने में बहुत बेकार है, यदि वह वास्तव में आपका इरादा था। या हो सकता है कि आप सिर्फ नेट पर बेतरतीब टिप्पणी करना पसंद कर रहे हों , यह बताना मुश्किल है :-) मैं जवाब से खड़ा हूं, ज़ाहिर है, उप-स्तंभ का उपयोग मापनीय नहीं है और लगभग हमेशा एक बुरा विचार है, जब तक कि यह उद्देश्य के लिए उपयोग नहीं किया जाता है वास्तव में फिक्सिंग उप स्तंभ का उपयोग।
paxdiablo

3
सवाल यह है कि सिंगल कॉलम को 2 में कैसे विभाजित किया जाए और फिर आप "डोन्ट टू दैट" कहकर जवाब देते हैं और फिर समझाते हैं कि उन्हें क्यों विभाजित किया जाना चाहिए। आपका पहला पैराग्राफ लगता है जैसे आप पक्ष में बहस कर रहे हैं या उन्हें एक कॉलम के रूप में रख रहे हैं, लेकिन दूसरे पैराग्राफ इसके विपरीत कहते हैं।
dfmiller

@Fmiller, शायद मैंने इस सवाल को गलत समझा, मुझे अब यकीन नहीं है कि अलगाव क्वेरी या तालिका में किया जाना था या नहीं। मैंने उत्तर को स्पष्ट रूप से स्पष्ट करने के लिए उत्तर दिया है।
पैक्सडीब्लो

काफी बेहतर। मैंने डेटाबेस को अपडेट करने के अलावा किसी चुनिंदा क्वेरी का उपयोग करने पर विचार नहीं किया। यह एक भयानक विचार होगा।
dfmiller

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'

यह क्षेत्र से पहली और अंतिम स्पेस सीमांकित सबस्ट्रिंग को पकड़ लेगा, जो सभी परिस्थितियों में काम नहीं करता है। उदाहरण के लिए, यदि नाम फ़ील्ड "लिली वॉन श्टुप" है, तो आपको पहले नाम, उपनाम के रूप में 'लिली', 'श्टुप्प' मिलेगा।
जॉन फ्रेंकलिन

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

4

MySQL में यह इस विकल्प पर काम कर रहा है:

SELECT Substring(nameandsurname, 1, Locate(' ', nameandsurname) - 1) AS 
       firstname, 
       Substring(nameandsurname, Locate(' ', nameandsurname) + 1)    AS lastname 
FROM   emp  

दूसरे क्षेत्र में स्ट्रिंग के आराम के लिए
एम। फराज

3

एकमात्र ऐसा मामला जहां आप इस तरह के फ़ंक्शन को चाहते हैं, एक अद्यतन क्वेरी है जो Firstname और Lastname को अलग-अलग फ़ील्ड में संग्रहीत करने के लिए आपकी तालिका को बदल देगा।

डेटाबेस डिजाइन को कुछ नियमों का पालन करना चाहिए, और डेटाबेस सामान्यीकरण सबसे महत्वपूर्ण लोगों में से है


अनावश्यक टिप्पणी के रूप में यह वही है जो पोस्टर ने पूछा; यह भी गलत है क्योंकि एक लाख बार आपको सामान्यीकरण के लिए एक स्ट्रिंग को विभाजित करने की आवश्यकता हो सकती है। अनसुना क्यों या कैसे यह कभी मतदान हुआ।
Daticon

स्प्लिट फ़ील्ड पर अनुक्रमित का उपयोग करना MySQL को एक पत्ती मल्चर में बनाने के रूप में असंभव है, लेकिन यह लोगों को इसके बारे में पूछने से नहीं रोकेगा। अच्छा जवाब - डेटाबेस SHOULD डेटा को दर्शाता है, न कि आपके लीफ मल्चर स्पेक्स को।
होल्डऑफ ह्यूंगर

2

मेरे पास एक कॉलम था जहां पहला और आखिरी नाम दोनों एक कॉलम में थे। पहला और अंतिम नाम एक अल्पविराम द्वारा अलग किया गया था। नीचे दिए गए कोड ने काम किया। जाँच / सुधार में कोई त्रुटि नहीं है। बस एक गूंगा बिखर गया। SQL कथन निष्पादित करने के लिए phpMyAdmin का उपयोग किया।

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

13.2.10 अद्यतन सिंटैक्स


1

यह यहाँ से smhg लेता है और MySQL में दिए गए सबस्ट्रिंग के लास्ट इंडेक्स से कर्ट करता है और उन्हें जोड़ती है। यह mysql के लिए है, मुझे जो कुछ भी चाहिए वह था, पहले नाम के लिए एक अच्छा विभाजन पाने के लिए last_name अंतिम नाम के साथ एक एकल शब्द, पहला नाम सब कुछ उस एकल शब्द से पहले, जहां नाम शून्य हो सकता है, 1 शब्द, 2 शब्द, या 2 से अधिक शब्द। Ie: अशक्त; मैरी; मैरी स्मिथ; मैरी ए स्मिथ; मेरी सू एलेन स्मिथ;

इसलिए यदि नाम एक शब्द या शून्य है, तो last_name शून्य है। यदि नाम> 1 शब्द है, तो last_name अंतिम शब्द है, और first_name अंतिम शब्द से पहले सभी शब्द हैं।

ध्यान दें कि मैं पहले ही जो स्मिथ जूनियर की तरह सामानों की छंटनी कर चुका हूं; जो स्मिथ एस्क। और इसलिए, मैन्युअल रूप से, जो दर्दनाक था, ज़ाहिर है, लेकिन ऐसा करने के लिए यह काफी छोटा था, इसलिए आप यह सुनिश्चित करना चाहते हैं कि नाम फ़ील्ड में डेटा का उपयोग करने का निर्णय लेने से पहले वास्तव में देखना चाहिए।

ध्यान दें कि यह परिणाम को भी प्रभावित करता है, इसलिए आप नामों के सामने या बाद में रिक्त स्थान के साथ समाप्त नहीं होते हैं।

मैं इसे केवल उन लोगों के लिए पोस्ट कर रहा हूं जो अपने तरीके से 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
    ) 
);

0

जब मैंने डेटा को पहले_नाम क्षेत्र में पहुँचाया, तो मैंने पहले_नाम को पहले_नाम और अंतिम_नाम में विभाजित किया। यह केवल अंतिम शब्द को अंतिम नाम फ़ील्ड में रखेगा, इसलिए "जॉन फिलिप्स सूसा" पहला नाम "जॉन फिलिप्स" और अंतिम नाम "सूसा" होगा। यह पहले से तय किए गए किसी भी रिकॉर्ड को ओवरराइट करने से भी बचता है।

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

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

-3

mysql 5.4 एक देशी विभाजन फ़ंक्शन प्रदान करता है:

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

1
क्या आप प्रलेखन के लिए एक लिंक प्रदान कर सकते हैं। Dev.mysql.com की एक खोज सूखी हुई है। इस फ़ंक्शन के लिए टिप्पणियों में धारा 12.5 में एक सामुदायिक सुझाव है।
DRAehal
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.