Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

MySQL स्ट्रिंग में किसी विशेष वर्ण के हर दूसरे उदाहरण को कैसे बदलें?

आपको अपने डेटा को सामान्यीकृत स्कीमा में संग्रहीत करने पर विचार करना चाहिए। आपके मामले में तालिका इस तरह दिखनी चाहिए:

| id | k |        v |
|----|---|----------|
|  1 | A |       10 |
|  1 | B |       20 |
|  1 | C |       30 |
|  2 | A | Positive |
|  2 | B | Negative |

यह स्कीमा अधिक लचीला है और आप देखेंगे कि क्यों।

तो दिए गए डेटा को नए स्कीमा में कैसे बदलें? आपको अनुक्रम संख्याओं वाली एक सहायक तालिका की आवश्यकता होगी। चूंकि आपका कॉलम varchar(255) . है आप इसमें केवल 128 मान (+ 127 सीमांकक) संग्रहीत कर सकते हैं। लेकिन चलिए सिर्फ 1000 नंबर बनाते हैं। आप पर्याप्त पंक्तियों वाली किसी भी तालिका का उपयोग कर सकते हैं। लेकिन चूंकि किसी भी MySQL सर्वर में information_schema.columns . होता है तालिका, मैं इसका उपयोग करूंगा।

drop table if exists helper_sequence;
create table helper_sequence (i int auto_increment primary key)
    select null as i
    from information_schema.columns c1
    join information_schema.columns c2
    limit 1000;

हम दो तालिकाओं को जोड़कर इस संख्या का उपयोग आपके स्ट्रिंग में मानों की स्थिति के रूप में करेंगे।

एक सीमांकित स्ट्रिंग से एक मान निकालने के लिए आप substring_index() . का उपयोग कर सकते हैं समारोह। स्थिति पर मान i होगा

substring_index(substring_index(t.options, '|', i  ), '|', -1)

आपकी स्ट्रिंग में आपके पास इसके मानों के बाद चाबियों का अनुक्रम होता है। एक कुंजी की स्थिति एक विषम संख्या है। तो अगर कुंजी की स्थिति i . है , संबंधित मान की स्थिति i+1 . होगी

स्ट्रिंग में सीमांकक की संख्या प्राप्त करने और हमारे शामिल होने को सीमित करने के लिए हम उपयोग कर सकते हैं

char_length(t.options) - char_length(replace(t.options, '|', ''))

डेटा को सामान्यीकृत रूप में संग्रहीत करने की क्वेरी होगी:

create table normalized_table
    select t.id
        , substring_index(substring_index(t.options, '|', i  ), '|', -1) as k
        , substring_index(substring_index(t.options, '|', i+1), '|', -1) as v
    from old_table t
    join helper_sequence s
      on s.i <= char_length(t.options) - char_length(replace(t.options, '|', ''))
    where s.i % 2 = 1

अब चलाएँ select * from normalized_table और आपको यह मिलेगा:

| id | k |        v |
|----|---|----------|
|  1 | A |       10 |
|  1 | B |       20 |
|  1 | C |       30 |
|  2 | A | Positive |
|  2 | B | Negative |

तो यह प्रारूप बेहतर विकल्प क्यों है? कई अन्य कारणों के अलावा, एक यह है कि आप इसे आसानी से अपने पुराने स्कीमा में बदल सकते हैं

select id, group_concat(concat(k, '|', v) order by k separator '|') as options
from normalized_table
group by id;

| id |               options |
|----|-----------------------|
|  1 |        A|10|B|20|C|30 |
|  2 | A|Positive|B|Negative |

या अपने इच्छित प्रारूप में

select id, group_concat(concat(k, '|', v) order by k separator ',') as options
from normalized_table
group by id;

| id |               options |
|----|-----------------------|
|  1 |        A|10,B|20,C|30 |
|  2 | A|Positive,B|Negative |

यदि आप सामान्यीकरण की परवाह नहीं करते हैं और केवल यह कार्य करना चाहते हैं, तो आप अपनी तालिका को

. से अपडेट कर सकते हैं
update old_table o
join (
    select id, group_concat(concat(k, '|', v) order by k separator ',') as options
    from normalized_table
    group by id
) n using (id)
set o.options = n.options;

और normalized_table ड्रॉप करें ।

लेकिन तब आप साधारण प्रश्नों जैसे

. का उपयोग नहीं कर पाएंगे
select *
from normalized_table
where k = 'A'

देखें rextester.com पर डेमो



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySQL INSERT - क्या फ़ील्ड नामों को बैकटिक/उच्चारण परिसीमन की आवश्यकता है?

  2. Mysql कई संग्रहीत प्रक्रियाओं से एक संग्रहीत कार्यविधि बनाता है

  3. Class.forName(com.mysql.jdbc.Driver).newInstance()

  4. MySql:यदि मान मौजूद है तो अद्यतन करें और INSERT

  5. Mysql द्वारा आदेश हटाएं