आपको अपने डेटा को सामान्यीकृत स्कीमा में संग्रहीत करने पर विचार करना चाहिए। आपके मामले में तालिका इस तरह दिखनी चाहिए:
| 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 पर डेमो