Трябва да помислите за съхраняване на вашите данни в нормализирана схема. Във вашия случай таблицата трябва да изглежда така:
<предварителен код>| ID | k | v ||----|---|----------|| 1 | A | 10 || 1 | Б | 20 || 1 | C | 30 || 2 | A | Положителен || 2 | Б | Отрицателен |Тази схема е по-гъвкава и ще видите защо.
И така, как да конвертирате дадените данни в новата схема? Ще ви трябва помощна таблица, съдържаща последователни номера. Тъй като колоната ви е varchar(255)
можете да съхранявате само 128 стойности (+ 127 разделителя) в него. Но нека просто създадем 1000 числа. Можете да използвате всяка таблица с достатъчно редове. Но тъй като всеки MySQL сървър има information_schema.columns
таблица, ще я използвам.
отпуснете таблицата, ако съществува helper_sequence;създайте таблица helper_sequence (i int auto_increment първичен ключ) изберете null като i от information_schema.columns c1 присъединете information_schema.columns c2 ограничение 1000;
Ще използваме тези числа като позиция на стойностите във вашия низ, като обединим двете таблици.
За да извлечете стойност от разделен низ, можете да използвате substring_index()
функция. Стойността на позиция i
ще бъде
substring_index(substring_index(t.options, '|', i ), '|', -1)
Във вашия низ имате поредица от ключове, последвани от нейните стойности. Позицията на ключа е нечетно число. Така че, ако позицията на ключа е i
, позицията на съответната стойност ще бъде i+1
За да получим броя на разделителите в низа и да ограничим нашето присъединяване, можем да използваме
char_length(t.options) - char_length(replace(t.options, '|', ''))
Заявката за съхраняване на данните в нормализирана форма би била:
създаване на таблица normalized_table изберете t.id , substring_index(substring_index(t.options, '|', i), '|', -1) като k, substring_index(substring_index(t.options, '|' , i+1), '|', -1) като v от old_table t присъединяване към помощна_последователност s на s.i <=char_length(t.options) - char_length(replace(t.options, '|', '')) където s.i % 2 =1
Сега стартирайте select * от normalized_table
и ще получите това:
Така че защо този формат е по-добър избор? Освен много други причини, едната е, че можете лесно да я конвертирате в старата си схема с
изберете идентификатор, group_concat(concat(k, '|', v) подреждане по k разделител '|') като опции от normalized_tablegroup по id;| ID | опции ||----|-----------------------|| 1 | A|10|B|20|C|30 || 2 | A|Положителен|B|Отрицателен |
или в желания от вас формат
изберете идентификатор, group_concat(concat(k, '|', v) подреждане по k разделител ',') като опции от normalized_tablegroup по id;| ID | опции ||----|-----------------------|| 1 | A|10,B|20,C|30 || 2 | A|Положителен, B|Отрицателен |
Ако не ви пука за нормализиране и просто искате тази задача да бъде изпълнена, можете да актуализирате таблицата си с
актуализиране на old_table ojoin ( изберете id, group_concat(concat(k, '|', v) подреждане по k разделител ',') като опции от нормализирана_таблица група по идентификатор) n с помощта на (id)set o.options =n.опции;
И пуснете normalized_table
.
Но тогава няма да можете да използвате прости заявки като
изберете *от normalized_table, където k ='A'
Вижте демото на rextester.com