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;
    

    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のデモ を参照してください。



    1. SQLAlchemyキャッシングを無効にする方法は?

    2. SQLServer2014での遅延耐久性

    3. SQLでのトランザクションを理解する

    4. my.cnfへの変更は有効になりません(Ubuntu 16.04、mysql 5.6)