Jnnbo: WHERE in PHP

Hallo,

ich habe ein kleines Problem, weiß nicht so recht wie ich es lösen soll. Ich habe Telefonnummern die unterschiedlich eingetragen wurden:

0221 - xx xx xx 1 0221 - xxx xxx xxx 1 0221 - xxxxxxxxx 0221-xxxx

Wenn ich mit

WHERE telNummer=

suche, wird mir nur ein Ergebnis angezeigt wenn es genau so geschrieben wird. Gibt es eine PHP Funktion wo ich diese Daten bei der suche in ein Format bringen kann um den Eintrag zu finden, egal wie er geschrieben ist?

akzeptierte Antworten

  1. Hallo,

    ich habe ein kleines Problem, weiß nicht so recht wie ich es lösen soll. Ich habe Telefonnummern die unterschiedlich eingetragen wurden:

    
    > > 0221 - xx xx xx 1
    > > 0221 - xxx xxx xxx 1
    > > 0221 - xxxxxxxxx
    > > 0221-xxxx
    
    

    Normalisiere die Nummern in der Datenbank. Auch für Datenbanken kann man (meistens) Benutzerfunktionen erstelle.

    PHP hat damit nichts zu tun

    Grüße TS

    1. Hallo TS,

      Normalisiere die Nummern in der Datenbank. Auch für Datenbanken kann man (meistens) Benutzerfunktionen erstelle.

      ich habe zu 95% keinen Einfluss auf die Schreibweise, das heißt ich müsste ALLE Daten von Hand prüfen was unmöglich ist.

      1. Hallo TS,

        Normalisiere die Nummern in der Datenbank. Auch für Datenbanken kann man (meistens) Benutzerfunktionen erstelle.

        ich habe zu 95% keinen Einfluss auf die Schreibweise, das heißt ich müsste ALLE Daten von Hand prüfen was unmöglich ist.

        Ich wiederhole mit anderen Worten:

        Schreibe dir eine Normalisierungsfunktion für die Datenbank.

        Fang an mit der Überlegung, was an der Formatierung geändert / korrigiert werden muss.

        1. Leerzeichen entfernen
        2. Trennzeichen ...

        Und dann code das.

        TS

        1. Hallo TS,

          Fang an mit der Überlegung, was an der Formatierung geändert / korrigiert werden muss.

          1. Leerzeichen entfernen
          2. Trennzeichen ...

          also so?:

          $test123 = str_replace(" ", "", $object->kd_telefon);
          $jo = str_replace("-", "", $test123);
          echo $jo;
          

          dann habe ich zwar bei der Ausgabe die Formatierung, aber nochmals, ich habe KEIN Einfluss was in der Datenbank steht und kann die Daten beim Eintragen auch nicht umformatieren, denn für ein externes Programm müssen die Daten genau so wieder exportiert werden.

          1. Hallo TS,

            Fang an mit der Überlegung, was an der Formatierung geändert / korrigiert werden muss.

            1. Leerzeichen entfernen
            2. Trennzeichen ...

            also so?:

            $test123 = str_replace(" ", "", $object->kd_telefon);
            $jo = str_replace("-", "", $test123);
            echo $jo;
            

            dann habe ich zwar bei der Ausgabe die Formatierung, aber nochmals, ich habe KEIN Einfluss was in der Datenbank steht und kann die Daten beim Eintragen auch nicht umformatieren, denn für ein externes Programm müssen die Daten genau so wieder exportiert werden.

            Aber nochmals: schreibe dir diese Funktion für die Datenbank!

            MySQLUDF

            1. Hallo TS,

              Aber nochmals: schreibe dir diese Funktion für die Datenbank!

              MySQLUDF

              du verstehst mein Problem nicht!

              1. U> Hallo TS,

                Aber nochmals: schreibe dir diese Funktion für die Datenbank!

                MySQLUDF

                du verstehst mein Problem nicht!

                Nun fang nicht an zu heulen, sondern lies dir das Kapitel 12 + 13 vom MySQL-Handbuch durch. Das Problem steckt in der Datenbank und lässt sich auch dort lösen. Warum willst es dannerst rausholen aus der Datenbank, was im übrigen nicht sinnvoll geht?

                Wenn es nur um Bindestrich und Leerzeichen geht, reicht schon ein geschachteltes replace(). Für komp,iziertere Normalisierungen schreibst du dir dann eben ein UDF.

                TS

  2. Hallo,

    ich habe ein kleines Problem, weiß nicht so recht wie ich es lösen soll. Ich habe Telefonnummern die unterschiedlich eingetragen wurden:

    0221 - xx xx xx 1 0221 - xxx xxx xxx 1 0221 - xxxxxxxxx 0221-xxxx

    Wenn ich mit

    WHERE telNummer=
    

    suche, wird mir nur ein Ergebnis angezeigt wenn es genau so geschrieben wird. Gibt es eine PHP Funktion wo ich diese Daten bei der suche in ein Format bringen kann um den Eintrag zu finden, egal wie er geschrieben ist?

    Hast Du es schon einmal statt mit einem "=" mit einem "like" probiert? Falls Du in Deinem Problemkontext like einsetzen kannst, könntest Du es vielleicht mit den SQL-Wildcards Deines DBMS probieren. Du müsstest Dir also überlegen, an welchen Stellen Du in den Nummern diese Jokerzeichen setzen kannst. Das ist wahrscheinlich ein mieserabler Filter in Deinem Fall, aber vielleicht hilft der Ansastz erst einmal ein Stückchen weiter.

  3. Tach!

    Ich habe Telefonnummern die unterschiedlich eingetragen wurden:
    Gibt es eine PHP Funktion wo ich diese Daten bei der suche in ein Format bringen kann um den Eintrag zu finden, egal wie er geschrieben ist?

    Nein. PHP kann ja nicht hellsehen, in welchem Format die Daten im DBMS stehen. Schon gar nicht, wenn jeder Datensatz unterschiedlich formatiert ist. Das Problem ist nicht mit PHP lösbar (jedenfalls nicht gescheit). Du solltest die Lösung im DBMS suchen, wie schon mehrfach empfohlen. Mit PHP musst du lediglich die Nutzereingaben aus dem Such-Feld gleichermaßen normalisieren, also beispielsweise für die erste der gleich folgenden Variante ebenfalls alle Nicht-Ziffern entfernen.

    Eine Variante wäre, mit REPLACE() die Leerzeichen zu entfernen. Das muss gegebenenfalls auch noch mit anderen Zeichen geschehen.

    WHERE REPLACE(REPLACE(telNummer, ' ', ''), '-', '') = '08154711'
    

    Sieht umständlich aus, ist es auch - besonders wenn noch weitere Zeichen hinzukommen. MySQL kennt kein Ersetzen mit regulären Ausdrücken, das würde die Sache vereinfachen.

    De nächste Variante wurde schon vorgeschlagen: LIKE. Wobei wohl RLIKE besser wäre. Zwischen jede Ziffer (auch vorn und hinten) müsste ein Jokerzeichen stehen, das beliebige Nicht-Ziffern zulässt (oder alternativ eine ausgewählte Anzahl Sonderzeichen "-+() "). Auch diese Variante ist nicht sehr toll. PHP kann dir lediglich beim Zusamenstückeln des Suchausdrucks helfen.

    Beide Varianten haben aber den Nachteil, dass ein Index nicht mehr zur Suche verwendet werden kann. Gut, das wird bei der anzunehmenden Anzahl der Datensätze nicht ins Gewicht fallen, aber ich wollte es nur mal erwähnt haben.

    Die beste Variante wäre, ein weiteres Feld einzufügen, das die Nummer im normalisierten Format aufnimmt, also nur die Ziffern. Dann ist diese Information zwar redundant, aber manchmal muss das so sein, damit man sich das Leben erleichtern kann.

    Die Abfrage ist dann ganz einfach. Aber wie bekommt man die Nummer normalisiert? Nun, für die bestehenden Daten einmal UPDATE drüberlaufen lassen, mit dem REPLACE() die Nicht-Ziffern rauswerfen. Wenn neue Daten hinzugefügt werden, dann kann das INSERT ein weiteres Feld mit der normalisierten Form einfügen. Die kann/muss dann von PHP erzeugt werden. Kommen die Daten auf anderem Wege in das DBMS, dann ist es günstiger, dass sich ein Insert-Trigger um das Zweitfeld kümmert. Gegebenenfalls muss auch noch einer für Updates hinzugefügt werden.

    dedlfix.

    1. Moin!

      Die beste Variante wäre, ein weiteres Feld einzufügen, das die Nummer im normalisierten Format aufnimmt, also nur die Ziffern. Dann ist diese Information zwar redundant, aber manchmal muss das so sein, damit man sich das Leben erleichtern kann.

      Die Abfrage ist dann ganz einfach. Aber wie bekommt man die Nummer normalisiert? Nun, für die bestehenden Daten einmal UPDATE drüberlaufen lassen, mit dem REPLACE() die Nicht-Ziffern rauswerfen. Wenn neue Daten hinzugefügt werden, dann kann das INSERT ein weiteres Feld mit der normalisierten Form einfügen. Die kann/muss dann von PHP erzeugt werden.

      Jepp! Man kann sich zwar für Mysql (mariasql kann regex-replace) eine funktion schreiben, aber das dürfte recht aufwendig werden.

      Also: Inserts, Updates und Vergleiche mit der "normalisierten" Form der Telefonnummer die in einer sorgfältig indexierten Spalte gespeichert werden (die andere dennoch (dann ohne Index) speichern!)

      Aus meiner Kiste:

      <?php
      ## filename: [/LIB-DIR/]ftx_cleartel.php
      if ( -1 < strpos($_SERVER['PHP_SELF'],'ftx_cleartel.php')) {
         ftx_cleartel_test();
      }
      
      function ftx_cleartel_test() {
          $telefonnummern = array(
              '456789',
              '45 67 89',
              '0123 456789',
              '0123 45 67 89',
              '0123-45 67 89',
              '0049 123 45 67 89',
              '0049 123 45 67 89',
              '+49 123 45 67 89',
              '+49(0)123 45 67 89',
              '+49 (0) 123-45 67 89',
              '+33 2 123 123 123 123'
          );
          foreach ($telefonnummern as $t) {
              echo "\nOriginal: $t", "\nGeklärt:  ", ftx_cleartel($t), "\n";
          }
      }
      
      function ftx_cleartel($t, $clear_vw_de=TRUE) {
          $t=preg_replace( '/^\+{1,2}/', '00', trim($t) );
          $t=str_replace( '(0)', '', $t );
          $t=preg_replace('/[^\d]/', '', $t);
          if ($clear_vw_de) {
              $t=preg_replace('/^0049/', '0', $t);
          }
      
          return $t;
      }
      

      Ausgaben des Selbsttests:

      Original: 456789
      Geklärt:  456789
      
      Original: 45 67 89
      Geklärt:  456789
      
      Original: 0123 456789
      Geklärt:  0123456789
      
      Original: 0123 45 67 89
      Geklärt:  0123456789
      
      Original: 0123-45 67 89
      Geklärt:  0123456789
      
      Original: 0049 123 45 67 89
      Geklärt:  0123456789
      
      Original: 0049 123 45 67 89
      Geklärt:  0123456789
      
      Original: +49 123 45 67 89
      Geklärt:  0123456789
      
      Original: +49(0)123 45 67 89
      Geklärt:  0123456789
      
      Original: +49 (0) 123-45 67 89
      Geklärt:  0123456789
      
      Original: +33 2 123 123 123 123
      Geklärt:  00332123123123123
      

      Jörg Reinholz

    2. Auch Tach :-)

      Kommen die Daten auf anderem Wege in das DBMS, dann ist es günstiger, dass sich ein Insert-Trigger um das Zweitfeld kümmert. Gegebenenfalls muss auch noch einer für Updates hinzugefügt werden.

      Und der kann dann auch die Normalisierungsfunktion benutzen :-)

      Grüße TS

  4. Hallo nochmal,

    ich habe ein kleines Problem, weiß nicht so recht wie ich es lösen soll.

    Das habe ich Dir mehrfach versucht mitzuteilen.

    Und dann habe ich Dir hier noch eine weitere Hilfestellung als Beispiel vorbereitet, wie Du das Problem elegant lösen könntest:

    delimiter //
    
    CREATE FUNCTION normalizeTelefon (number varchar(50)) returns varchar(50)
    begin
    	declare counter int default 1;
    	declare len int;
    	declare allowed varchar(10) default '0123456789';
    	declare result varchar(50) default '';
    	
    	set len = char_length(number);
    
    	while counter <= len DO
    		if locate(substr(number, counter, 1), allowed) > 0 then
    			set result = concat(result, substr(number, counter, 1));
    		end if; 
    
    	   set counter = counter + 1;
    	end while; 
    	
    	return result;
    end //
    
    delimiter ;
    

    Diese Funktion fügst Du deiner Dartenbank einfach hinzu. Und dann kannst Du z.B. folgendermaßen abfragen:

    
        select `id`, `telefonnummer` 
        from `telefon` 
        where normalizeTelefon($suchnummer) 
            like concat ('%', normalizeTelefon(`telefonnummer`));
        
    

    $suchnummer musst Du in der Abfrage ersetzen gegen die gesuchte Nummer.
    In der Funktion musst Du eventuell noch das '+49' oder ähnlich berücksichrtigen, wenn es notwendig ist.

    Viel Erfolg

    TS