正規化されたスキーマにデータを保存することを検討する必要があります。あなたの場合、テーブルは次のようになります。
| 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;
2つのテーブルを結合することにより、この数値を文字列内の値の位置として使用します。
区切られた文字列から値を抽出するには、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 |
では、なぜこの形式がより良い選択なのですか?他の多くの理由に加えて、1つは、
を使用して古いスキーマに簡単に変換できることです。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のデモ を参照してください。