sql >> Database >  >> RDS >> Mysql

Hoe vervang je elke andere instantie van een bepaald teken in een MySQL-tekenreeks?

Overweeg om uw gegevens op te slaan in een genormaliseerd schema. In jouw geval zou de tabel er als volgt uit moeten zien:

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

Dit schema is flexibeler en u zult zien waarom.

Dus hoe de gegeven gegevens in het nieuwe schema om te zetten? U hebt een hulptabel nodig met volgnummers. Aangezien uw kolom varchar(255) . is je kunt er maar 128 waarden (+ 127 scheidingstekens) in opslaan. Maar laten we gewoon 1000 getallen maken. U kunt elke tabel met voldoende rijen gebruiken. Maar aangezien elke MySQL-server de information_schema.columns . heeft tafel, ik zal hem gebruiken.

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;

We zullen deze getallen gebruiken als positie van de waarden in je string door de twee tabellen samen te voegen.

Om een ​​waarde uit een string met scheidingstekens te extraheren, kunt u de substring_index() . gebruiken functie. De waarde op positie i zal zijn

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

In je string heb je een reeks sleutels gevolgd door zijn waarden. De positie van een sleutel is een oneven getal. Dus als de positie van de sleutel i . is , is de positie van de corresponderende waarde i+1

Om het aantal scheidingstekens in de string te krijgen en onze join te beperken, kunnen we

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

De vraag om de gegevens in een genormaliseerde vorm op te slaan zou zijn:

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

Voer nu select * from normalized_table uit en je krijgt dit:

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

Dus waarom is dit formaat een betere keuze? Naast vele andere redenen, is een ervan dat je het gemakkelijk naar je oude schema kunt converteren met

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 |

of naar uw gewenste formaat

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 |

Als normalisatie u niet interesseert en u wilt gewoon dat deze taak wordt uitgevoerd, kunt u uw tabel bijwerken met

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;

En laat de normalized_table vallen .

Maar dan kunt u geen eenvoudige zoekopdrachten gebruiken, zoals

select *
from normalized_table
where k = 'A'

Bekijk de demo op rextester.com



  1. Hoe de prestaties van Moodle te benchmarken?

  2. MySQL Databases vergelijken

  3. Stel de tekenset en sortering van een tabel in MariaDB in

  4. Manieren waarop toegang uw bedrijf geld kan besparen