2016-05-05 1 views
0
mit Mysql ersetzen

Mit der Funktionersetzen nur in gewünschtem Spiel

Replace(FieldX,'FindString','ReplaceString') where FieldX = 'ABC' 

Adaequat ersetzen, bis es ein zusätzliches Spiel in der Zeichenfolge, die ich will nicht zu ersetzen.

In meinem Fall habe ich ein Adressfeld, das ich als ALL CAPS bekam. Allerdings möchte ich 'PR' auf 'Prairie' ändern, wenn es auftritt, wie:

  • 'PR%'
  • '% PR'
  • % PR%‘

Doch wenn ich tun:

Update TableA 
Set Address=Replace(Address,'PR','PRAIRIE') 
where Address like '%PR ' or Address like 'PR %' or Address like '% PR ' 

Dann 'PR PRIMO' wird 'PRAIRIE PRAIRIEIMP'

dachte ich, obwohl es das Ausmaß meiner Änderungen gegeben umständlich wird ich diese

Update TableA 
Set Address=Replace(Address,'PR ','PRAIRIE ') 
where Address like like 'PR %' 

Update TableA 
Set Address=Replace(Address,' PR',' PRAIRIE') 
where Address like like '% PR' 

Update TableA 
Set Address=Replace(Address,' PR ',' PRAIRIE ') 
where Address like like '% PR %' 

in drei Abfragen lösen könnte Aber das wird mühsam sein (weit mehr Ersatz wieder ich zu tun habe und andere Fragen) und scheint Es könnte immer noch Fehler erzeugen, die ich nicht erwartet habe. Die Ersetzungstabellen sind ebenfalls sehr groß und dies verdreifacht die Verarbeitungszeit.

Hat jemand in einen Weg gerannt, um dies zu lösen, ist ein weniger gewagter Ansatz? Wenn dies ein Regex wäre, könnte ich damit durchkommen, denke ich, aber ich habe herausgefunden, dass Regex einen großen Aufwand für diese Art von Ersatz mit sich bringt und wie gesagt die Tabellen sind groß.

+0

Angesichts der fehlenden tatsächlichen regulären Ausdrücken, haben Sie ein Skript in Betracht gezogen, die Sie haben über die verschiedenen Kombinationen gehen könnte im Auge behalten in einer Schleife? Ich habe diesen Ansatz bereits verwendet und es hat sehr gut funktioniert, wenn Single-Query-Updates nicht praktikabel/möglich sind. Ist eine längere Sub-String möglich? – ray

+0

MySQL hat keine eingebaute Regexp Replace-Funktion, aber Sie können einige UDFs finden, indem Sie dafür googlen. – Barmar

+0

@ray, wenn ich an diesen Punkt komme, verwende ich im Allgemeinen Excel glauben oder nicht und Tabellen, Felder und Term/ersetzen Begriff in Zellen und dann eine String-Funktion mit End; in der äußersten rechten Zelle. Dann kopiere ich einfach nach unten und voila. Ich bin ziemlich resigniert, dies hier zu tun. Ich landete mit etwa 300 kürzeren Suchanfragen, was meinen Kopf schlägt, wenn ich mir einen Workaround ausprobiere. – user3649739

Antwort

1

Sie können dies tun (denke ich), indem Sie alles mit zwei Leerzeichen umwickeln und dann ersetzen. (Diese kümmert sich um die^PR und PR $ Fällen, wenn eine Regex ohne pr zu beeinflussen innerhalb von Worten wie dies würde nie einen Platz haben, und danach Verwenden trim als letzten Schritt die Räume zu entfernen.

mysql> SELECT TRIM(REPLACE(' PR PRIMO ', ' PR ', ' PRAIRIE ')); 
+--------------------------------------------------+ 
| TRIM(REPLACE(' PR PRIMO ', ' PR ', ' PRAIRIE ')) | 
+--------------------------------------------------+ 
| PRAIRIE PRIMO         | 
+--------------------------------------------------+ 
1 row in set (0.00 sec) 

Beachten Sie, dass die Verwendung einer Tabelle zum Koordinieren des Updates Ihnen viel Zeit ersparen kann, wenn Sie viele Ersetzungen in großen Tabellen verwenden.Im Folgenden finden Sie ein Beispiel für das Hinzufügen und Entfernen der Leerzeichen über concat im Update, sodass Sie dem Ersetzungswert nur normale Werte hinzufügen können . Tabelle

Code:

DROP TABLE IF EXISTS hugeTable; 
CREATE TABLE hugeTable(address CHAR(32)); 

DROP TABLE IF EXISTS replacements; 
CREATE TABLE replacements(find CHAR(8), `replace` CHAR(8)); 

INSERT INTO hugeTable VALUES ('PR PRIMO'); 

INSERT INTO replacements VALUES ('PR', 'PRAIRIE'); 

SELECT * FROM hugeTable; 

UPDATE hugeTable A, replacements B 
SET A.address = TRIM(REPLACE(CONCAT(' ', A.address, ' '), CONCAT(' ', B.find, ' '), CONCAT(' ', B.`replace`, ' '))); 

SELECT * FROM hugeTable; 

Abfrage:

mysql> CREATE TABLE hugeTable(address CHAR(32)); 
Query OK, 0 rows affected (0.10 sec) 

mysql> 
mysql> DROP TABLE IF EXISTS replacements; 
Query OK, 0 rows affected (0.01 sec) 

mysql> CREATE TABLE replacements(find CHAR(8), `replace` CHAR(8)); 
Query OK, 0 rows affected (0.02 sec) 

mysql> 
mysql> INSERT INTO hugeTable VALUES ('PR PRIMO'); 
Query OK, 1 row affected (0.04 sec) 

mysql> 
mysql> INSERT INTO replacements VALUES ('PR', 'PRAIRIE'); 
Query OK, 1 row affected (0.01 sec) 

mysql> 
mysql> SELECT * FROM hugeTable; 
+----------+ 
| address | 
+----------+ 
| PR PRIMO | 
+----------+ 
1 row in set (0.00 sec) 

mysql> 
mysql> UPDATE hugeTable A, replacements B 
    -> SET A.address = TRIM(REPLACE(CONCAT(' ', A.address, ' '), CONCAT(' ', B.find, ' '), CONCAT(' ', B.`replace`, ' '))); 
Query OK, 1 row affected (0.01 sec) 
Rows matched: 1 Changed: 1 Warnings: 0 

mysql> 
mysql> SELECT * FROM hugeTable; 
+---------------+ 
| address  | 
+---------------+ 
| PRAIRIE PRIMO | 
+---------------+ 
1 row in set (0.00 sec) 

Grüße,

James

+0

Das ist eigentlich ziemlich erstaunlich. Ich habe es mit deinen Mysqls getestet und 'Primo PR' und 'W Primo PR' und 'W PR Primo' hinzugefügt, d. H. Es wird Anfang, Mitte, Ende gefunden/ersetzt. Es geht so gut und schnell.Mein 500-Abfrageskript von letzter Nacht läuft noch immer, wenn es zu 'where'% PR 'oder' wo '% PR%' kommt, dauert es bei diesen Millionen Datensatztabellen ewig. Etwa, um dies zu stoppen (was einen guten Tag der Verarbeitung und Prüfung mit Ihrer Abfrage dauert und melden zurück/Update – user3649739

+0

Ok Ich teste gleichzeitig die Brute-Force-Mysql auf einer 26mil-Record-Tabelle und Ihre auf einer 2,6 Millionen Datensatz Tabelle (Da ich nicht zu jeder Zeit verlieren will, melde ich mich zurück. "Mein erster Test lief auf den ersten 1000 Datensätzen, mit 19 Update, in ca. 5 Minuten. Bare nicht gut für 2600x, aber ich hoffe, dass es nicht ist linear :) – user3649739

+0

Füllen Sie die Ersetzungstabelle mit allen Ersetzungen? Oder führen Sie INSERT und UPDATE für jeden Ersatz separat aus? Es sollte eine Aussage sein. Versuchen Sie auch, eine WHERE auf dem Update (der gleiche INSTR wie das SET, da dies die Dinge beschleunigen kann) versuchen später, bin weg von meinem Computer. –

1

Obwohl ich James Scott Antwort akzeptiert, die eine große Lösung war, habe ich ein paar Mods machen und dachte, dass ich hier schließen würde, da seine Lösung ein eleganter und mit ein paar Verbesserungen machte dieses Update tatsächlich möglich.

seinen Kernsatz unter Hinweis war:

SET A.address = 
TRIM(REPLACE(CONCAT(' ', A.address, ' '), 
CONCAT(' ', B.find, ' '), 
CONCAT(' ', B.`replace`, ' '))); 
  1. Ich benutzte das Kernkonzept der Begriff der Polsterung und Suchen/Ersetzen in der `Set‘ Funktion schlug er vor.
  2. Anstatt die Suche/ersetzen eine zweite Tabelle zu sein, die einen Join erfordert (was bedeutete, 300 Datensätze zu 26 Millionen Datensätze zu verbinden), machte ich ein Skript (mit Excel), um eine einzige Abfrage pro Suchen/Ersetzen zu machen.

  3. Ich habe eine where-Klausel hinzugefügt, um die Menge der zu untersuchenden Datensätze zu reduzieren, was mit 26 Millionen Datensätzen kritisch ist (ja, ich habe die Abfrage w und w/o Where getestet). Dies war nur möglich wegen der Ergänzung der Auffüllung (concat), da ich jetzt einen einzigen Durchlauf mit %findterm% gegenüber den zusätzlichen zwei Durchgängen von % findterm und findterm % machen konnte, während die Auffüllung sicherstellt, dass festerm ein diskretes Wort ist.

  4. Schließlich, weil die findterms entweder als Versalien (PL) oder Proper (Pl) ich eine Funktion, die ich hier unempfindlich ersetzen für Fall installiert gespeichert werden kann (Case Insensitive REPLACE for MySQL), so dass ich nicht jede Abfrage laufen musste zweimal Platz für jeden Fall.

Eine Beispielabfrage sah wie folgt aus

SET address = 
TRIM(REPLACE_ci(CONCAT(' ',address, ' '), 
CONCAT(' ', 'PL', ' '), 
CONCAT(' ', 'Place', ' '))) where address like '%PL%'; 

die Statistiken auf der Update-Lauf gemacht erfolgreich:

  • 300 Suchen/Ersetzen-Begriffe/abfragt
  • 5 Tabellen
  • Gesamt 42 Millionen Datensätze
  • Größte Tabelle 26 Millionen r ecords
  • Kleinste Tabelle 1/2 Millionen Datensätze
  • 3,5 Millionen Datensätze aktualisiert
  • Zehn Stunden