Rolf B: Telefonnummern in Adressdatenbank

Beitrag lesen

Hallo Otto,

Alle +, 49, () usw. habe ich schon aus dem Suchwort rausgefiltert

Aus dem Suchwort? Also dem Input für die Suche? Ja, da musst Du natürlich auch filtern.

Du musst die Sonderzeichen aus dem Suchbegriff entfernen, aber aus den Telefonnummern in der DB auch! Deswegen habe ich Dir eine generierte Spalte vorgeschlagen, die eine normalisierte Version der Telefonnummer enthält.

Ich suche jetzt mit LIKE und "%15735499117%"

Fail - das würde auch die 0015735499117 (+1-573-549-9117) finden. Das ist eine Windstream-Nummer für ein Mobiltelefon in Middletown, Montgomery County, Missouri (ehemals Prairie Township). Nomen est Omen - das ist tiefstes Redneck Land. 167 Einwohner, 1/3 unter der Armutsschwelle und 3 Kirchen 👀

Deswegen fragte ich nach dem Bedarf für eine Normalisierung auf nationaler oder internationaler Ebene. Aber normalisieren musst Du!

Wenn normalisiert ist, suchst Du einfach mit = statt mit LIKE.

Zum Normalisieren kann man eine Replace-Kette verwenden:

REPLACE(REPLACE(REPLACE(REPLACE(nummer,
                                ' ', ''),
                        '-', ''),
                '(', ''),
        ')', '')

das entfernt Space, Minus und Klammern. Ich habe die zugehörigen Parameter untereinandergestellt, damit man nicht den Überblick verliert.

Das Problem, ob Du eine nationale Nummer (015735499117) oder eine internationale Nummer (0015735499117 oder +15735499117) hast, wird dadurch nicht behoben und es ist auch nicht so einfach behebbar. Man kann das mit einem CASE-Ausdruck angehen, aber das ist kompliziert.

CASE 
WHEN SUBSTR(nummer, 1, 2) = '00' THEN nummer
WHEN SUBSTR(nummer, 1, 1) = '+' THEN CONCAT('00', SUBSTR(nummer,2))
WHEN SUBSTR(nummer, 1, 1) = '0' THEN CONCAT('0049', SUBSTR(nummer,2)
ELSE '???'
END

Diese Case-Operation würde 00-Nummern unverändert lassen, aus +49... eine 0049-Nummer machen und nationale Nummern (0157354...) zu 0049157354 internationalisieren.

Und um DAS musst Du dann noch die REPLACE-Kette legen. Ziemlich umfänglich.

Besser ist es, für sowas eine Function als Stored Routine zu schreiben, das macht die Sache deutlich übersichtlicher.

In MYSQL ist beim Erzeugen eines generierten Suchfeldes noch zu beachten, dass nur InnoDB eine virtuell generierte Spalte indexieren kann. MyISAM kann nur auf stored generated columns einen Index legen. Guckst Du hier, Stichwort GENERATED.

Was Du keinesfalls tun darfst, ist eine Normalisierung in dem SELECT, der die Suche durchführt. Das führt dazu, dass kein Index genutzt werden kann und MySQL einen Tablescan machen muss. Tablescans sind der Tod jeder DB-Performance. Mit dem indexierten Suchfeld gelingt ein Index-Seek.

Rolf

--
sumpsi - posui - obstruxi