{"id":55000733,"date":"2010-08-01T00:00:00","date_gmt":"2020-05-22T22:06:40","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=733"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Fehlertolerantes_Suchen","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/","title":{"rendered":"Fehlertolerantes Suchen"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg06.met.vgwort.de\/na\/c493928b7cec4a60a4a8fda88b8c459a\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>&#8222;Firma Waren-Paradies, Konstanze Meyer am Apparat. Was kann ich f&uuml;r Sie tun&#8220; &#8211; &#8222;Ja, Katschmarek. Ich hatte letzte Woche eine Bestellung aufgegeben; die m&ouml;chte ich gerne stornieren.&#8220; &#8211; &#8222;Wie war der Name&#8220; &#8211; &#8222;Katschmarek!&#8220; Die Kundenbetreuerin Frau Meyer gibt den Namen in die Suchmaske des Kundenformulars ihrer Datenbank zur Bestellabwicklung ein. Die Datenbank findet den Kunden nicht. &#8222;W&uuml;rden Sie den Namen bitte buchstabieren&#8220; &#8211; &#8222;K-A-C-S-M-A-R-E-K&#8220; &#8211; &#8222;Mit C-S&#8220; &#8211; &#8222;Ja, genau!&euro; Ein Gl&uuml;ck, dass Herr Kacsmarek nicht mit &#8222;Kaufmann-Anton-C&auml;sar-Samuel-Martha-&#8230;&#8220; antwortete, denn dann h&auml;tte Frau Meyer wahrscheinlich nochmals nachgefragt &#8230;<\/b><\/p>\n<p>Dieser Fall ist wohl nicht selten. Hat man nur das gesprochene Wort zur Verf&uuml;gung, so d&uuml;rfte man mit der korrekten Schreibweise gerade von Namen h&auml;ufig &uuml;berfordert sein. Eine Datenbank, die Begriffe nur anhand exakter &Uuml;bereinstimmung vergleicht, wird dem nicht gerecht.<\/p>\n<p>Dabei h&auml;tte der Entwickler der Datenbank Frau Meyer die Sache leichter machen k&ouml;nnen, wenn er Methoden zur fehlertoleranten Suche, eine &#8222;Unscharfsuche&#8220;, eingebaut h&auml;tte. Solche Routinen versuchen, zwei Begriffe auf gr&ouml;&szlig;tm&ouml;gliche &Uuml;bereinstimmung zu vergleichen, und geben die plausibelsten Treffer in einer Liste zur&uuml;ck, aus der man schlie&szlig;lich den wahrscheinlichsten ausw&auml;hlen kann.<\/p>\n<p>Anwendungsbereiche f&uuml;r eine solche fehlertolerante Suche gibt es viele: Au&szlig;er Nachnamen w&auml;ren etwa Stra&szlig;ennamen Kandidaten, Bezeichnungen von Artikeln, L&auml;ndernamen oder selbst Telefonnummern, die Zahlendreher enthalten. Wenn auch Sie den Benutzern Ihrer Datenbanken &auml;hnlichen Komfort bieten m&ouml;chten, dann integrieren Sie einfach eine L&ouml;sung, wie die nachfolgend vorgestellte.<\/p>\n<p><b>Was ist &auml;hnlich<\/b><\/p>\n<p>Bevor man einen Algorithmus entwickelt, der zwei Strings auf &auml;hnlichkeit untersucht, muss man sich zun&auml;chst fragen, was unter &#8222;&auml;hnlichkeit&#8220; &uuml;berhaupt zu verstehen ist. Was f&uuml;r den Cortex eines Menschen kein Problem zu sein scheint, bereitet dem Linguisten und erst recht dem Programmierer erhebliches Kopfzerbrechen.<\/p>\n<p>Zudem kann die Fehlerquelle f&uuml;r falsche Schreibweise auch noch ganz unterschiedlich sein. Im Beispiel oben handelt es sich um ein phonetisches Problem: die Aussprache beider Begriffe ist identisch, ihre L&auml;nge unterscheidet sich aber um zwei Buchstaben. Von den Lauten her hat Frau Meyer nichts falsch gemacht.<\/p>\n<p>Doch selbst dann, wenn sie ungarische Vorfahren h&auml;tte und die richtige Schreibweise w&uuml;sste, h&auml;tte ihr ein Schreibfehler unterlaufen und die Eingabe &#8222;Kascmarek&#8220; sein k&ouml;nnen &#8211; sie hat sich schlicht vertippt. Die Aufgabe liegt also darin, einerseits Schreib- und Tippfehler aufzufangen und andererseits phonetische &auml;hnlichkeiten zu erkennen.<\/p>\n<p>Die rein programmtechnische Frage ist au&szlig;erdem, wie eine &auml;hnlichkeitsfunktion das Ma&szlig; der &Uuml;bereinstimmung widergeben soll. Es haben sich hier zwei Verfahren eingeb&uuml;rgert, die sinnbildlich so aussehen:<\/p>\n<pre>fuSimilar (\"Begriff1\" , \"Begriff2\") = TRUE oder FALSE\r\nfuSimilar (\"Begriff1\" , \"Begriff2\") = 0...100<\/pre>\n<p>Im ersten Fall sagt die Funktion lediglich, ob die Begriffe &uuml;berhaupt &auml;hnlich sind oder nicht (Ja oder Nein).<\/p>\n<p>Im zweiten wird ein Wert zur&uuml;ckgegeben, der mit 100 v&ouml;llige &Uuml;bereinstimmung, mit 0 &uuml;berhaupt keine und dazwischen teilweise &Uuml;bereinstimmung feststellt.<\/p>\n<p><b>Phonetik<\/b><\/p>\n<p>Viele Algorithmen spezialisieren sich darauf, Begriffe zu vergleichen, die gleich oder m&ouml;glichst &auml;hnlich ausgesprochen werden. Dazu werden, bevor es zum eigentlichen String-Vergleich kommt, zun&auml;chst beide Begriffe einer phonetischen Analyse unterzogen. <\/p>\n<p>Nehmen wir mal den Namen &#8222;Becker&#8220;. Hier besteht die deutsche Eigent&uuml;mlichkeit darin, dass ein &#8222;CK&#8220; genau so ausgesprochen wird, wie das &#8222;K&#8220; allein. Man k&ouml;nnte den String also analysieren und das &#8222;CK&#8220; zun&auml;chst durch ein &#8222;K&#8220; ersetzen.<\/p>\n<p>Nach dieser Vorbehandlung w&auml;ren die beiden Begriffe &#8222;Becker&#8220; und &#8222;Beker&#8220; identisch. Ein Algorithmus mit phonetischem Pr&auml;prozessor w&uuml;rde nun den Wert 100 f&uuml;r den Vergleich zur&uuml;ckgeben.<\/p>\n<p>Da dies nicht wirklich zutrifft, ziehen die g&auml;ngigen Algorithmen hier einfach einen kleinen Ausgleichswert ab &#8211; etwa 10 -, falls der Pr&auml;prozessor tats&auml;chlich an den Eingangs-Strings geschraubt hat. In diesem Fall w&auml;re das Ergebnis folglich 90, was man als &#8222;so gut wie, aber nicht identisch&#8220; interpretieren k&ouml;nnte.<\/p>\n<p>Das Beispiel bietet noch mehr Potenzial: Im Deutschen lauten &#8222;E&#8220; und &#8222;&auml;&#8220; gleich. Somit kann ein &#8222;&auml;&#8220; ebenfalls durch ein &#8222;E&#8220; ersetzt werden. Das &#8222;&auml;&#8220; wiederum k&ouml;nnte auch umlautlos als &#8222;AE&#8220; daherkommen. Folgende Namen w&auml;ren dann nach Durchlaufen des Pr&auml;prozessors identisch:<\/p>\n<pre>\"Becker\", \"Beker\", \"B&auml;ker\", \"B&auml;cker\", \"Baeker\", \"Baecker\"<\/pre>\n<p>Alle sechs resultierten im vorbehandelten String &#8222;Beker&#8220;.<\/p>\n<p>Zu &uuml;berlegen w&auml;re auch, ob nicht Vokalverdoppelungen reduziert werden k&ouml;nnten:<\/p>\n<pre>\"Beeker\" &gt; \"Beker\"<\/pre>\n<p>Das Spiel kann beliebig fortgesetzt werden. So ist die Endung &#8222;er&#8220; im Deutschen etwa weitgehend lautgleich mit &#8222;a&#8220;. Aus &#8222;Becker&#8220; w&uuml;rde &#8222;Beka&#8220;.<\/p>\n<p>Damit das funktioniert, reicht ein einfaches Replace auf die Eingangs-Strings allerdings nicht aus. Soll alles korrekt laufen, so muss ein Begriff eigentlich in Silben aufgetrennt, die Position einer Zeichenkombination ermittelt und au&szlig;erdem analysiert werden, ob vor einer Konsonantenkombination ein Vokal steht oder nicht.<\/p>\n<p>Und damit w&auml;ren wir schon bei den Nachteilen eines phonetischen Pr&auml;prozessors: Die Berechnung kostet sehr viel Zeit und ist nicht sehr zuverl&auml;ssig, weil etwa eine Silbentrennung nicht mit hinreichender Performance zu bewerkstelligen ist.<\/p>\n<p>Au&szlig;erdem funktioniert der phonetische Pr&auml;prozessor nur f&uuml;r eine bestimmte Sprache. Im Slawischen etwa w&uuml;rde der Name &#8222;Becker&#8220; eher wie &#8222;Betschker&#8220; ausgesprochen. W&auml;re die Zielsprache also Serbisch, so ben&ouml;tigte man daf&uuml;r einen v&ouml;llig anderen Pr&auml;prozessor.<\/p>\n<p>Gerade f&uuml;r Namensvergleiche eignet sich das Verfahren daher weniger, weil &#8211; siehe Eingangsbeispiel &#8222;Kacsmarek&#8220; &#8211; internationale Namen im deutschen Sprachraum immer h&auml;ufiger vorkommen.<\/p>\n<p>Aus Performancegr&uuml;nden verwenden &auml;hnlichkeitsalgorithmen deshalb normalerweise nur sehr einfache phonetische Pr&auml;prozessoren. Im Ergebnis sind sie dann mal besser, mal schlechter als Algorithmen ohne Pr&auml;prozessor. Es kommt immer auf den genauen Anwendungsbereich an, ob man sie einsetzen sollte oder nicht.<\/p>\n<p>In der sp&auml;ter vorgestellten Demo k&ouml;nnen Sie sich selbst ein Bild davon machen. Zwei der verwendeten Algorithmen k&ouml;nnen optional auch mit phonetischem Pr&auml;prozessor betrieben werden. Testen Sie einfach, ob die phonetische Vorbehandlung etwas bringt.<\/p>\n<p><b>Vertippt<\/b><\/p>\n<p>Sie kennen das sicher: Sie tippen schnell mal ein Wort in die Tastatur und haben schlie&szlig;lich statt &#8222;Becker&#8220; den Text &#8222;Bekcer&#8220; auf dem Schirm &#8211; ein Verdreher. Oder die letzte Taste wurde nicht richtig gedr&uuml;ckt, was &#8222;Becke&#8220; zum Ergebnis hat.<\/p>\n<p>Aufgabe der Datenbank soll nun sein, trotzdem den beabsichtigten Begriff zu finden. Wie kann man das anstellen<\/p>\n<p><b>&auml;hnlichkeitsalgorithmen<\/b><\/p>\n<p>Fast alle g&auml;ngigen Algorithmen verwenden f&uuml;r unseren Zweck das sogenannte Distanz-Verfahren. Am bekanntesten ist die Levenshtein-Distanz, benannt nach ihrem Sch&ouml;pfer.<\/p>\n<p>Dabei wird ermittelt, wie viele Zeichen der Eingangs-Strings jeweils an der gleichen Position genau &uuml;bereinstimmen, beziehungsweise, ob sich eine &uuml;bereinstimmende Position m&ouml;glicherweise in der N&auml;he befindet.<\/p>\n<p>Sehen wir uns &#8222;Becker&#8220; vs. &#8222;Bekcer&#8220; n&auml;her an (s. Bild 1). An vier Positionen befinden sich &uuml;bereinstimmende Zeichen, die den Gewichtungsfaktor 1 bekommen. Bei zwei Zeichen gibt es jeweils &Uuml;bereinstimmung an um eins verschobenen Positionen. Diese werden nun willk&uuml;rlich mit dem Faktor 0.5 belegt, was aussagen soll, dass eine m&ouml;gliche Gleichheit besteht.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2010_04\/FehlertoleranteSuche_5-web-images\/becker.png\" alt=\"becker.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 1: Vergleich von Becker und Bekcer<\/span><\/b><\/p>\n<p>Bereits hier wird sichtbar, dass solche Berechnungen die Realit&auml;t nur ann&auml;hernd widerspiegeln und auf reinen, zum Teil stochastischen Annahmen beruhen. Und genau dies ist die Kunst solcher Algorithmen: Sie sollen dem, was ein Mensch als &auml;hnlich empfindet, m&ouml;glichst nahekommen.<\/p>\n<p>Deshalb gibt es auch Hunderte solcher Verfahren, die sich manchmal nur in kleinen, aber wichtigen Details unterscheiden, und ganze Studienprojekte besch&auml;ftigen ihre Eleven mit der Optimierung solcher Routinen.<\/p>\n<p>Wer hier einen n&auml;heren Blick riskieren will, der schaue sich auf der Seite von <b>SimMetrics<\/b> [1] um, einem Open-Source-Projekt der englischen Universit&auml;t Sheffield. Dort sind zahlreiche Algorithmen in einem Projekt zusammengefasst und bewertet worden, das auch als Visual Studio.NET-Paket zur Verf&uuml;gung steht.<\/p>\n<p>Die jeweiligen Algorithmen sind darin &uuml;bersichtlich in einzelnen C-Libraries abgelegt. Zur Warnung: Wie bei Uni-Projekten &uuml;blich, ist der Verst&auml;ndnis-Level hier nur eine Sache f&uuml;r wissenschaftlich Interessierte.<\/p>\n<p>Um beim Beispiel zu bleiben &#8211; in Bild 2 hat sich jemand noch mehr vertan. Die Buchstaben sind ziemlich durcheinander und doch erkennt man mit dem Auge auf einen Blick, dass &auml;hnlichkeit zwischen beiden Begriffen besteht, obwohl nur drei Zeichen an der korrekten Position &uuml;bereinstimmen. Die anderen sind mehr oder weniger verschoben und dem tragen die Faktoren 0.5 und 0.25 Rechnung.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2010_04\/FehlertoleranteSuche_5-web-images\/becker2.png\" alt=\"becker2.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 2: Vergleich von Becker und Bekecr<\/span><\/b><\/p>\n<p>Letztlich summiert man nun die Gewichtungsfaktoren und setzt sie in Beziehung zur durchschnittlichen Gesamtzahl an Zeichen beider Strings. Im letzten Beispiel:<\/p>\n<pre>f = 4.25\/6 = 0.7083<\/pre>\n<p>Da die R&uuml;ckgabewerte im Bereich von 0 bis 100 liegen sollen, wird dieses Ergebnis noch mit 100 multipliziert, gerundet und Sie erhalten 71.<\/p>\n<p>In der praktischen Auswertung w&uuml;rde man nun ein Limit setzen und annehmen, dass etwa alle Ergebnisse oberhalb von 75 als hinreichend &auml;hnlich anzusehen seien. In diesem Fall fiele das letzte Beispiel aus der Liste der plausiblen Ergebnisse heraus, das vorige aber gen&uuml;gte der Bedingung:<\/p>\n<pre>f = Round (5\/6 * 100) = 83<\/pre>\n<p>&Uuml;brigens kommt derselbe Wert auch dann heraus, wenn man &#8222;Becker&#8220; und &#8222;Wecker&#8220; vergleicht. Dieses Ergebnis kann man schon weniger akzeptieren. Doch daf&uuml;r gibt es leider keine Regel: Es hat sich stochastisch schlicht ergeben, dass der Anfangsbuchstabe seltener falsch geschrieben wird.<\/p>\n<p><!--30percent--><\/p>\n<p>Also belegen viele Verfahren den ersten oder die ersten Zeichen beim Vergleich mit h&ouml;heren Gewichtungsfaktoren. W&uuml;rde man etwa die &Uuml;bereinstimmung des ersten Zeichens mit dem Faktor 2 versehen, dann s&auml;he die Rechnung wie folgt aus:<\/p>\n<pre>\"BECKER\" vs. \"BECLER\"<\/pre>\n<p>F&uuml;nf Zeichen stimmen &uuml;berein, eines nicht. Das erste Zeichen bekommt aber den Faktor 2, sodass die Summe 6 ergibt. Der eine Faktor 2 muss nun nat&uuml;rlich in den L&auml;ngendivisor mit einbezogen werden, weshalb als Ergebnis 6\/(6+1) = 86 steht.<\/p>\n<pre>\"BECKER\" vs. \"WECKER\"<\/pre>\n<p>Auch hier stimmen f&uuml;nf Zeichen &uuml;berein. Da der Anfangsbuchstabe jedoch falsch ist, fehlt nun der Faktor 2: 5\/6 = 83. <\/p>\n<p>In einer Liste m&ouml;glicher Treffer, die absteigend nach dem &auml;hnlichkeitswert sortiert w&auml;re, bef&auml;nde sich also &#8222;BECLER&#8220; weiter oben.<\/p>\n<p>Abschlie&szlig;end der Hinweis, dass diese Darstellung lediglich das Grundprinzip des Distanzverfahrens widergibt. Die tats&auml;chlichen Implementationen sind deutlich komplexer. Um diese brauchen Sie sich allerdings auch nicht weiter zu k&uuml;mmern, denn Sie selbst werden wahrscheinlich keine eigenen Algorithmen entwickeln wollen. &Uuml;berlassen Sie das ruhig den Professoren an den Instituten.<\/p>\n<p>Es ist nur gut zu wissen, wie die Verfahren prinzipiell arbeiten, um deren Ergebnisse besser interpretieren zu k&ouml;nnen.<\/p>\n<p><b>Implementationen<\/b><\/p>\n<p>Von den Verfahren, die weite Verbreitung erfahren haben, ist in erster Linie der uralte Soundex-Algorithmus (1918!) zu erw&auml;hnen. Dieser abstrahiert Eingabe-Strings stark, indem er daraus einen Zeichencode mit genau vier Zeichen erzeugt.<\/p>\n<p>Dabei werden nur die vorderen Buchstaben ber&uuml;cksichtigt, die hinteren abgeschnitten und au&szlig;erdem Buchstabengruppen Zahlen zugeordnet. Es werden auch nur Konsonanten in die Berechnung einbezogen.<\/p>\n<p>Aus &#8222;Becker&#8220; wird etwa &#8222;B226&#8220;. Den exakt gleichen Code erh&auml;lt man auch mit der Eingabe &#8222;Busserl&#8220;. Soundex sieht zwei Strings als &auml;hnlich an und gibt dann eine 1 aus, wenn die errechneten Codes genau &uuml;bereinstimmen, und andernfalls eine 0. Im Grunde handelt es sich damit bei Soundex um einen Pr&auml;prozessor.<\/p>\n<p>Ob &#8222;Becker&#8220; und &#8222;Busserl&#8220; tats&auml;chlich &auml;hnlich sind, mag jeder selbst entscheiden, und au&szlig;erdem, ob die Ausgabewerte <b>1 <\/b>und <b>0 <\/b>den Anforderungen an eine fehlertolerante Suche wirklich gen&uuml;gen. Abgesehen davon, dass Soundex nur den Anfang eines Begriffs untersucht, die Konsonanten stark reduziert und Vokale au&szlig;en vor l&auml;sst, ist er auch noch auf die englische Sprache &#8222;optimiert&#8220;.<\/p>\n<p>Ich mache keinen Hehl aus meiner Einsch&auml;tzung, dass Soundex f&uuml;r eine ernsthafte &auml;hnlichkeitssuche nicht zu gebrauchen ist, obwohl er sogar in die SQL-Funktionen von DBMS wie MSSQL, Oracle und MySQL aufgenommen wurde &#8211; warum auch immer.<\/p>\n<p>Daran &auml;ndert leider auch der abgeleitete und etwas verbesserte Metaphone-Algorithmus nichts. Metaphone erzeugt nicht nur vier Zeichencodes, sondern beliebig lange, und teilt die Konsonanten nicht nur in sechs Gruppen ein. Er ist aber ebenso auf die englische Sprache abgestimmt und gibt als Ergebnis lediglich eine <b>1 <\/b>oder eine <b>0 <\/b>zur&uuml;ck.<\/p>\n<p>Diese beiden Algorithmen sind hier nur der weiten Verbreitung wegen erw&auml;hnt worden. Mit dem oben dargestellten Distanzverfahren haben sie nichts zu tun. Dessen wichtigster Vertreter wiederum ist der bereits 1965 entwickelte Levenshtein-Algorithmus. <\/p>\n<p>Er arbeitet im Prinzip ziemlich genau so, wie im &#8222;Becker-Beispiel&#8220; erl&auml;utert, hat aber den Nachteil, dass keine variablen Gewichtungen eingerechnet werden und kein Pr&auml;prozessor vorgesehen ist.<\/p>\n<p>Deshalb haben sich Myriaden von Entwicklern an seine Verbesserung gemacht. Daraus haben sich Verfahren wie Ratcliff\/Obershelp und die von Jaro und Winkler ergeben. Beide sind relativ neueren Datums &#8211; entwickelt Mitte der Neunziger Jahre &#8211; und kommen in der Demo zu diesem Beitrag zum Einsatz.<\/p>\n<p>Wie sie genau funktionieren, lasse ich au&szlig;en vor und ebenso die ganzen anderen Verfahren, die Sie etwa im SimMetrics-Paket [1] finden k&ouml;nnen.<\/p>\n<p class=\"zwischen-berschrift-oberer-spaltenrand\">Beispieldatenbank<\/p>\n<p>Starten Sie die Beispieldatenbank <b>similar.mdb<\/b>, die lediglich ein Formular (s. Bild 3) enth&auml;lt, in dem ein w&auml;hlbarer Name nach verschiedenen Methoden mit 10.000 Stammdatens&auml;tzen auf &auml;hnlichkeit verglichen wird. Als Ergebnis erhalten Sie eine gefilterte Liste der zutreffendsten Nachnamen aus der Stammdatentabelle.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2010_04\/FehlertoleranteSuche_5-web-images\/demoform.png\" alt=\"demoform.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 3: &auml;hnlichkeitsvergleich eines Namens mit den Stammdaten einer Tabelle<\/span><\/b><\/p>\n<p>Die Datenbank greift teilweise auf externe Komponenten zu, auf die Verweise gesetzt sind. Das sind die beiden ActiveX-DLLs <b>dbstrings.dll <\/b>und <b>mSimilarity.dll<\/b>. Damit beim Start der Demo keine Fehlermeldungen wegen nicht vorhandener Verweise auftauchen, m&uuml;ssen diese beiden DLLs zun&auml;chst im System registriert werden.<\/p>\n<p>Dazu f&uuml;hren Sie einfach die Datei <b>register_dll.bat <\/b>aus. Unter Vista und Windows 7 muss sie dezidiert mit <b>Als Administrator ausf&uuml;hren<\/b> aufgerufen werden, unter Windows XP sollten Sie unter einem Administrator-Account arbeiten.<\/p>\n<p>Die Stammdatentabelle, auf die das Formular aufsetzt, ist sehr einfach gestrickt: Neben der Prim&auml;rschl&uuml;ssel-ID gibt es nur ein Feld f&uuml;r Nachname (<b>Name<\/b>) und eins f&uuml;r den Vornamen einer Person.<\/p>\n<p>Auf das Nachname-Feld ist ein Index gesetzt &#8211; das sollte man grunds&auml;tzlich tun, wenn dieses Feld sp&auml;ter in Such- und Vergleichsoperationen einbezogen werden soll.<\/p>\n<p>Schreiten Sie zur Tat: In das oberste Textfeld des Formulars geben Sie einen beliebigen Namen ein, wahlweise mit falscher Schreibweise, oder belassen es beim voreingetragenen Katschmarek. W&auml;hlen Sie ein Vergleichsverfahren &uuml;ber die Optionsgruppe aus und klicken Sie auf die Schaltfl&auml;che <b>Suchen<\/b>.<\/p>\n<p>Daraufhin wird eine Abfrage ausgef&uuml;hrt, die &auml;hnlichkeitsfunktionen des Moduls <b>mdlPhonetics <\/b>aufruft.<\/p>\n<p>Das Ergebnis der nach &auml;hnlichkeit absteigend sortierten Abfrage bekommen Sie anschlie&szlig;end im Unterformular zu Gesicht, und au&szlig;erdem wird noch angezeigt, wie lange die Abfrage f&uuml;r ihre Berechnung in Millisekunden brauchte, sodass Sie die Performance der einzelnen Verfahren beurteilen k&ouml;nnen. Auf die Funktionsweise der Methoden wird im Folgenden noch n&auml;her eingegangen.<\/p>\n<p>Warum, werden Sie vielleicht fragen, braucht es da wieder einmal externe Komponenten, deren Weitergabe und Registrierung dem Entwickler das Leben schwer machen<\/p>\n<p>Die Antwort finden Sie schnell, wenn Sie die beiden Methoden <b>Ratcliff Schmidt Prepared <\/b>und <b>Ratcliff Schmidt Prepared VBA <\/b>ausf&uuml;hren. Beide verwenden den gleichen Code, nur dass im einen Fall der Code rein in VBA gehalten ist (<b>clsRatcliffSchmidtVBA<\/b>), im anderen in einer unter VB6 erstellten und kompilierten DLL untergebracht ist. Die Ausf&uuml;hrungszeit unterscheidet sich um den Faktor 7! <\/p>\n<p>Da VBA nur halbkompilierten P-Code erzeugt, eine VB6-DLL bei entsprechender Einstellung aber nativen Prozessor-Code, kann es in der Performance gerade bei einfachen Operationen nicht mithalten.<\/p>\n<p>Und das auch dann, wenn, wie in der Klasse <b>clsRatcliffSchmidtVBA<\/b>, ausschlie&szlig;lich mit Integer-Arrays gearbeitet wird und nicht direkt mit String-Operationen, was die Sache nochmals langsamer machen w&uuml;rde.<\/p>\n<p>Kommen wir zum Beispielformular zur&uuml;ck. Alle Optionen, bis auf das nur der Vollst&auml;ndigkeit hinzugef&uuml;gte <b>LIKE<\/b>, verwenden als Basis eine Abfrage, die wie in Bild 4 aussieht. Der SQL-Ausdruck dieser Abfrage ist hier wiedergegeben:<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2010_04\/FehlertoleranteSuche_5-web-images\/abfrage.png\" alt=\"abfrage.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 4: Abfrage zum Filtern der Stammdatentabelle &uuml;ber eine &auml;hnlichkeitsfunktion<\/span><\/b><\/p>\n<pre>SELECT TOP 25 Stammdaten.[Name],\r\nFirst(Stammdaten.Vorname) AS Vorname, RatcliffSchmidt([Name]) AS n\r\nFROM Stammdaten\r\nGROUP BY Stammdaten.[Name]\r\nHAVING (RatcliffSchmidt([Name]))&gt;=MinSim())\r\nORDER BY RatcliffSchmidt([Name]) DESC;<\/pre>\n<p>Damit im Ergebnis nur eindeutige Nachnamen erscheinen, also Datens&auml;tze mit dem gleichen Nachnamen nicht mehrfach auftreten, ist die Abfrage nach diesem Feld gruppiert. Au&szlig;erdem wird die Ergebnisliste abgeschnitten, damit sie nicht zu viele Datens&auml;tze zur&uuml;ckgibt, was &uuml;ber den <b>TOP<\/b>-Operator geschieht.<\/p>\n<p>Auf die Ausgabe des Vornamens h&auml;tte man auch verzichten k&ouml;nnen. Sie ist nur kosmetischer Natur.<\/p>\n<p>Der Kern der Abfrage steht in der dritten Spalte, in der der Vergleichswert <b>n <\/b>zwischen dem Feld <b>Nachname <\/b>und dem in das Formular eingegebenen Text errechnet wird &#8211; hier mittels der Funktion <b>RatcliffMoss<\/b>. Doch wo findet sich in der Abfrage dieser im Formular eingegebene Begriff als Vergleichsparameter<\/p>\n<p>Gar nicht, denn er wurde in eine VBA-Routine ausgelagert:<\/p>\n<pre>Public Function RatcliffMoss(S1 As String) _\r\n    As Integer\r\n    RatcliffMoss = _\r\n    dbstrings.RatcliffSimilar(S1, sComp)\r\nEnd Function<\/pre>\n<p>Da Abfragen nicht Funktionen aus verwiesenen Bibliotheken direkt ansprechen k&ouml;nnen, braucht man ohnehin eine VBA-Funktion als Mittler. Die Funktion <b>RatcliffMoss <\/b>verwendet dabei die Bibliothek <b>dbstrings <\/b>aus der gleichnamigen DLL.<\/p>\n<p>Als Eingabeparameter erwartet sie einen String, der hier aus dem Namensfeld der Tabelle kommt, und vergleicht ihn mit einem String der Variablen <b>sComp<\/b>. Diese Variable ist global deklariert und wurde zuvor mit dem im Formular eingegebenen Text besetzt.<\/p>\n<p>Auf diese Weise schl&auml;gt man zwei Fliegen mit einer Klappe.<\/p>\n<p>Bliebe noch der als Kriterium f&uuml;r den Vergleichswert in der Abfrage vorhandene Ausdruck <b>MinSim()<\/b>. Auch das ist eine VBA-Funktion, die lediglich den Wert einer globalen Integer-Variablen <b>m_factor <\/b>zur&uuml;ckgibt, welche vorher &uuml;ber das Kombinationsfeld <b>Limit<\/b> im Formular gesetzt wurde:<\/p>\n<pre>Public Function MinSim() As Integer\r\n    MinSim = m_factor\r\nEnd Function<\/pre>\n<p>Damit kann man schon im Formular einstellen, wie gro&szlig; die Trefferliste sein soll. Je kleiner dieser <b>Limit<\/b>-Wert ist, desto gr&ouml;&szlig;ere Abweichungen der &auml;hnlichkeit werden ber&uuml;cksichtigt. Zur Erinnerung: Der Wert <b>100 <\/b>symbolisiert vollst&auml;ndige &Uuml;bereinstimmung, der Wert <b>0 <\/b>sagt aus, dass keinerlei &auml;hnlichkeit vorhanden ist. Alle Werte dazwischen versinnbildlichen &#8222;mehr oder weniger &auml;hnlich&#8220;.<\/p>\n<p>Als plausible Limits haben sich Werte um die <b>70<\/b> herum herausgestellt.<\/p>\n<p>Jedes der Verfahren im Formular benutzt eine Abfrage nach diesem Aufbau, die ihrerseits jeweils eine eigene VBA-Funktion f&uuml;r den String-Vergleich aufruft. Das Abfrageergebnis wird schlie&szlig;lich einfach dem Unterformular <b>sfrmDemo<\/b> als <b>RecordSource <\/b>zugewiesen, was die Liste zur Anzeige bringt.<\/p>\n<p><b>Ratcliff und Konsorten<\/b><\/p>\n<p>Ich habe mich aus Gr&uuml;nden der Verf&uuml;gbarkeit und der Leistungsf&auml;higkeit f&uuml;r zwei Verfahren entschieden: Ratcliff und Jaro-Winkler. F&uuml;r den Ratcliff-Algorithmus gibt es dabei mehrere Varianten, die sich auch ein wenig im Ergebnis unterschieden, weil der Algorithmus in verschiedenen Modifikationen implementiert sein kann.<\/p>\n<p>Die <b>dbstrings.dll <\/b>wurde in Delphi programmiert und enth&auml;lt nur eine einzige Funktion: <b>RatcliffSimilar<\/b>.<\/p>\n<p>Nach &Uuml;bergabe zweier Strings gibt sie den &Uuml;bereinstimmungswert zur&uuml;ck:<\/p>\n<pre>n = RatCliffSimilar ( String1, String2)<\/pre>\n<p>Statt in Abfragen kann man sie nat&uuml;rlich auch sonst wo in VBA-Routinen einsetzen und etwa Recordsets durchlaufen.<\/p>\n<p>Der Quellcode f&uuml;r die Bibliothek stammt &uuml;brigens aus Routinen der inzwischen verschollenen Schmiede Mindsprings Corp., wobei Teile in Assembler ausgef&uuml;hrt sind. <b>RatcliffSimilar <\/b>bewertet den Anfangsbuchstaben und vollst&auml;ndige Vorkommen von Substrings h&ouml;her.<\/p>\n<p>Dass VB6 nicht langsamer sein muss als Assembler oder C, zeigt die DLL <b>mSimilarity<\/b>, welche alle weiteren Verfahren beherbergt. <\/p>\n<p>Die Methode <b>RatcliffSchmidt <\/b>wurde von Olaf Schmidt [2] entwickelt, sicherlich einen der gewieftesten VB6-Programmierer &uuml;berhaupt. Den Quellcode seiner Routinen k&ouml;nnen Sie sich im Klassenmodul <b>clsRatcliffSchmidtVBA <\/b>ansehen.<\/p>\n<p>Die Eingabe-Strings werden hier zun&auml;chst in Integer-Arrays &uuml;berf&uuml;hrt und anschlie&szlig;end werden Vergleichoperationen ausschlie&szlig;lich &uuml;ber numerische Werte vorgenommen, was die Performance erheblich erh&ouml;ht, weil VB bei String-Operationen sehr langsam ist.<\/p>\n<p>Im Grunde arbeiten die Routinen damit &auml;hnlich wie Codes auf C-Basis, die mit Zeigern hantieren. Eine ersch&ouml;pfende Darstellung der Programmiertechniken w&uuml;rde an dieser Stelle den Rahmen sprengen.<\/p>\n<p><b>RatcliffSchmidt <\/b>enth&auml;lt einen Pr&auml;prozessor, der in der DLL-Ausf&uuml;hrung optional auch ausgeschaltet werden kann. Der Aufruf gesch&auml;he dann so:<\/p>\n<pre>n = RatcliffSchmidt( String1, String2, False)<\/pre>\n<p>Mit <b>True<\/b> statt <b>False <\/b>ist er eingeschaltet. Dieser optionale Parameter stellt eine Erweiterung meinerseits dar.<\/p>\n<p>Jaro-Winkler ist ebenfalls ein Distanzverfahren. Meine Implementation in der <b>mSimilarity.dll <\/b>leitet sich von verschiedenen C-Sources ab. Die internen Gewichtungsfaktoren und der hier ebenfalls optionale Pr&auml;prozessor sind Marke Eigenbau.<\/p>\n<p>Beim Pr&auml;prozessor, der die Routine etwas verlangsamt, wurde versucht, besser auf den Wechsel von Vokalen und Konsonanten in den Strings zu reagieren, was Fehler bei zusammengesetzten W&ouml;rtern verringern soll. Zudem wurden mehr Konsonanten- und Vokalkombinationen ber&uuml;cksichtigt als bei Schmidts Pr&auml;prozessor.<\/p>\n<p>Ansonsten arbeitet auch diese Methode intern mit Integer-Arrays und Pseudo-Zeigern und ist hinreichend schnell.<\/p>\n<p><b>Performance<\/b><\/p>\n<p>Zur Messung der Geschwindigkeiten aller Verfahren befindet sich in der Demo das Modul <b>mdlPerformance<\/b>, in dem die beiden Prozeduren <b>CheckPerformance1 <\/b>und <b>CheckPerformance2<\/b> aufgerufen werden k&ouml;nnen.<\/p>\n<p>Die zweite Prozedur vergleicht in einer Schleife dauernd zwei feste Strings, die erste durchl&auml;uft alle Datens&auml;tze eines Recordsets, was eher den Aufgaben einer Datenbank gerecht wird.<\/p>\n<p>Der Spitzenreiter ist Schmidts Ratcliff-Verfahren, etwas langsamer ist die dbstrings-Variante. Jaro-Winkler h&auml;lt gut mit, kann aufgrund des etwas komplexeren Distanzverfahrens aber Ratcliff nicht ganz das Wasser reichen. Mit eingeschaltetem Pr&auml;prozessor verdoppelt sich dessen Laufzeit.<\/p>\n<p>Das Schlusslicht bildet die reine VBA-Variante, die hier glatt um den Faktor 25 langsamer ist als die identische Implementation in der DLL.<\/p>\n<p><b>RatcliffSchmidt<\/b> schafft in einer Sekunde durchschnittlich circa 700.000 Vergleichsaufrufe. Das h&auml;ngt aber auch davon ab, wie lang die Eingabe-Strings sind!<\/p>\n<p>In eine Abfrage aufgenommen, relativieren sich diese Werte deutlich, weil JET schlie&szlig;lich noch Zeit f&uuml;r ganz andere Berechnungen ben&ouml;tigt. Bis auf die VBA-Variante lassen sich alle Verfahren gut in Datenbanken einsetzen.<\/p>\n<p><b>Ergebnisse<\/b><\/p>\n<p>Geschwindigkeit allein n&uuml;tzt nichts, wenn das Ergebnis schwach ausf&auml;llt. Geben Sie in das Demoformular verschiedene Namen ein, &uuml;berpr&uuml;fen Sie die Ergebnisliste mit den vorhandenen Verfahren und &auml;ndern Sie gegebenenfalls den Limit-Parameter, denn die R&uuml;ckgabewerte der Algorithmen sind nicht exakt &uuml;bertragbar.<\/p>\n<p>Sowohl die absoluten Werte machen &auml;nderungen am Limit notwendig, wie auch die &#8222;Spreizung&#8220; nach &auml;hnlichkeit. Der voreingestellte Wert <b>70 <\/b>ist schon mal ein guter Default f&uuml;r die meisten Zwecke. Nur Jaro-Winkler mit Pr&auml;prozessor braucht manchmal ein niedrigeres Limit von etwa <b>60<\/b>.<\/p>\n<p>Sie werden feststellen, dass es kein Verfahren gibt, dem grunds&auml;tzlich der Vorzug zu geben w&auml;re. Jedes hat seine St&auml;rken und Schw&auml;chen. <\/p>\n<p>So f&uuml;hren die Prepared-Varianten (Pr&auml;prozessor eingeschaltet) manchmal gar zu schlechteren Werten, weil Zeichenkombinationen falsch interpretiert werden.<\/p>\n<p>Gut sind Pr&auml;prozessoren, wenn in der Quelle h&auml;ufig Schreibweisen ohne Umlaute vorkommen, wie etwa &#8222;G&auml;bler&#8220; vs. &#8222;Gaebler&#8220;. Schlechter hingegen k&ouml;nnen sie sein, wenn viele nichtdeutsche Begriffe vorkommen. Oben hatten wir diesen Fall mit &#8222;Kacsmarek&#8220;. <\/p>\n<p><b>RatCliffMoss <\/b>ist guter Allrounder, w&auml;hrend bei <b>RatcliffSchmidt <\/b>die Spreizung der &auml;hnlichkeitswerte etwas gr&ouml;&szlig;er ist, sodass weniger unplausible Begriffe in der Ergebnisliste auftauchen.<\/p>\n<p><b>Jaro-Winkler <\/b>ist vielleicht noch etwas treffgenauer, aber daf&uuml;r auch langsamer.<\/p>\n<p><b>Jaro-Winkler <\/b>mit Pr&auml;prozessor eliminiert wahrscheinlich am besten unsinnige Ergebnisse, braucht daf&uuml;r aber auch einen ziemlich genau justierten Limit-Parameter. <\/p>\n<p><b>Einsatz<\/b><\/p>\n<p>Wenn Sie die L&ouml;sungen in Ihre eigenen Datenbanken aufnehmen wollen, dann verwenden Sie als Basis am besten das Modul <b>mdlPhonetics<\/b>.<\/p>\n<p>Und denken Sie daran, die jeweilige DLL weiterzugeben und zu registrieren &#8211; mit einer Ausnahme: Das Registrieren auf dem Zielsystem k&ouml;nnen Sie sich ersparen, wenn Sie die <b>DirectCOM<\/b>-L&ouml;sung nehmen.<\/p>\n<p>Dazu ist wiederum die Zusatz-DLL <b>directcom.dll <\/b>von Olaf Schmidt n&ouml;tig, die das Instanzieren von Klassenobjekten in externen Komponenten &uuml;ber API-Funktionen auch ohne deren Registrierung schafft.<\/p>\n<p>Dann ben&ouml;tigen Sie auch zus&auml;tzlich das Klassenmodul <b>clsRatcliffDirectCOM <\/b>der Demodatenbank. Wer also auf dem Zielsystem keine Administratorrechte vorfindet, sollte diese L&ouml;sung erw&auml;gen.<\/p>\n<p>Alles Weitere bleibt Ihnen &uuml;berlassen. Als Anregung hier der Aufbau einer realistischen L&ouml;sungsvariante:<\/p>\n<p>Anforderung war, dass in Klienten-Datens&auml;tzen nach Eingabe des Stra&szlig;ennamens und der Hausnummer automatisch von der Datenbank die Postleitzahl in das entsprechende Formularfeld eingetragen werden soll. Dazu gleicht die eingebaute Routine den Stra&szlig;ennamen mit einer Tabelle ab, die beispielsweise alle Stra&szlig;ennamen Berlins enth&auml;lt.<\/p>\n<p>Findet sie keine exakte &Uuml;bereinstimmung, so tritt die &auml;hnlichkeitssuche auf den Plan. Die Stra&szlig;ennamen werden nun analog zum Demoformular der Beispieldatenbank mit der <b>RatcliffSimilar<\/b>-Methode abgeglichen, die Ergebnisliste wird in einem Popup-Formular pr&auml;sentiert und mit dem Hinweis versehen, dass keine solche Stra&szlig;e existiere und man nun bitte in der Liste den zutreffenden Eintrag anklicken m&ouml;ge. Erst danach wird aus einer weiteren Hausnummerntabelle die zur Stra&szlig;e geh&ouml;rige Postleitzahl ermittelt und ins Formularfeld eingetragen. <\/p>\n<p><b>Zusammenfassung<\/b><\/p>\n<p>&auml;hnlichkeitsvergleiche werden eigentlich in fast jeder Datenbank ben&ouml;tigt. Dass sie nur selten implementiert werden, liegt wohl daran, dass Access und JET von Haus aus keine entsprechenden Funktionen vorhalten.<\/p>\n<p>Mit den hier vorgestellten L&ouml;sungen rund um zwei frei verf&uuml;gbare ActiveX-DLLs wird diesem Umstand abgeholfen. Testen Sie die Ergebnisse und entscheiden sich am besten f&uuml;r einen passenden Algorithmus f&uuml;r Ihren Einsatzbereich. Die Entscheidung wird davon beeinflusst, ob Sie etwa nach Nachnamen, Stra&szlig;ennamen oder Artikelbezeichnungen suchen m&ouml;chten.<\/p>\n<p>Sie k&ouml;nnen uns gerne mitteilen, welche L&ouml;sung Sie f&uuml;r die leistungsf&auml;higste halten.<\/p>\n<p class=\"zwischen-berschriftquellen\">Quellen:<\/p>\n<p class=\"quellen\">[1] SimMetrics: http:\/\/www.dcs.shef.ac.uk\/~sam\/simmetrics.html<\/p>\n<p class=\"quellen\">[2] Olaf Schmidt: http:\/\/www.thecommon.net<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>Demo.zip<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/{E381E61B-EFE0-4059-93F5-0208F8DBCEF0}\/aiu_733.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8222;Firma Waren-Paradies, Konstanze Meyer am Apparat. Was kann ich f&uuml;r Sie tun&#8220; &#8211; &#8222;Ja, Katschmarek. Ich hatte letzte Woche eine Bestellung aufgegeben; die m&ouml;chte ich gerne stornieren.&#8220; &#8211; &#8222;Wie war der Name&#8220; &#8211; &#8222;Katschmarek!&#8220; Die Kundenbetreuerin Frau Meyer gibt den Namen in die Suchmaske des Kundenformulars ihrer Datenbank zur Bestellabwicklung ein. Die Datenbank findet den Kunden nicht. &#8222;W&uuml;rden Sie den Namen bitte buchstabieren&#8220; &#8211; &#8222;K-A-C-S-M-A-R-E-K&#8220; &#8211; &#8222;Mit C-S&#8220; &#8211; &#8222;Ja, genau!&#8220; Ein Gl&uuml;ck, dass Herr Kacsmarek nicht mit &#8222;Kaufmann-Anton-C&auml;sar-Samuel-Martha-&#8230;&#8220; antwortete, denn dann h&auml;tte Frau Meyer wahrscheinlich nochmals nachgefragt &#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662010,66042010,44000025],"tags":[],"class_list":["post-55000733","post","type-post","status-publish","format-standard","hentry","category-662010","category-66042010","category-VBA_und_Programmiertechniken"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Fehlertolerantes Suchen - Access im Unternehmen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Fehlertolerantes Suchen\" \/>\n<meta property=\"og:description\" content=\"&quot;Firma Waren-Paradies, Konstanze Meyer am Apparat. Was kann ich f&uuml;r Sie tun&quot; - &quot;Ja, Katschmarek. Ich hatte letzte Woche eine Bestellung aufgegeben; die m&ouml;chte ich gerne stornieren.&quot; - &quot;Wie war der Name&quot; - &quot;Katschmarek!&quot; Die Kundenbetreuerin Frau Meyer gibt den Namen in die Suchmaske des Kundenformulars ihrer Datenbank zur Bestellabwicklung ein. Die Datenbank findet den Kunden nicht. &quot;W&uuml;rden Sie den Namen bitte buchstabieren&quot; - &quot;K-A-C-S-M-A-R-E-K&quot; - &quot;Mit C-S&quot; - &quot;Ja, genau!&quot; Ein Gl&uuml;ck, dass Herr Kacsmarek nicht mit &quot;Kaufmann-Anton-C&auml;sar-Samuel-Martha-...&quot; antwortete, denn dann h&auml;tte Frau Meyer wahrscheinlich nochmals nachgefragt ...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-22T22:06:40+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg06.met.vgwort.de\/na\/c493928b7cec4a60a4a8fda88b8c459a\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"22\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Fehlertolerantes_Suchen\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Fehlertolerantes_Suchen\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Fehlertolerantes Suchen\",\"datePublished\":\"2020-05-22T22:06:40+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Fehlertolerantes_Suchen\\\/\"},\"wordCount\":4281,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Fehlertolerantes_Suchen\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/c493928b7cec4a60a4a8fda88b8c459a\",\"articleSection\":[\"2010\",\"4\\\/2010\",\"VBA und Programmiertechniken\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Fehlertolerantes_Suchen\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Fehlertolerantes_Suchen\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Fehlertolerantes_Suchen\\\/\",\"name\":\"Fehlertolerantes Suchen - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Fehlertolerantes_Suchen\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Fehlertolerantes_Suchen\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/c493928b7cec4a60a4a8fda88b8c459a\",\"datePublished\":\"2020-05-22T22:06:40+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Fehlertolerantes_Suchen\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Fehlertolerantes_Suchen\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Fehlertolerantes_Suchen\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/c493928b7cec4a60a4a8fda88b8c459a\",\"contentUrl\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/c493928b7cec4a60a4a8fda88b8c459a\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Fehlertolerantes_Suchen\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Fehlertolerantes Suchen\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"name\":\"Access im Unternehmen\",\"description\":\"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access\",\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/access-im-unternehmen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\",\"name\":\"Andr\u00e9 Minhorst Verlag\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"contentUrl\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"width\":370,\"height\":111,\"caption\":\"Andr\u00e9 Minhorst Verlag\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Fehlertolerantes Suchen - Access im Unternehmen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/","og_locale":"de_DE","og_type":"article","og_title":"Fehlertolerantes Suchen","og_description":"\"Firma Waren-Paradies, Konstanze Meyer am Apparat. Was kann ich f&uuml;r Sie tun\" - \"Ja, Katschmarek. Ich hatte letzte Woche eine Bestellung aufgegeben; die m&ouml;chte ich gerne stornieren.\" - \"Wie war der Name\" - \"Katschmarek!\" Die Kundenbetreuerin Frau Meyer gibt den Namen in die Suchmaske des Kundenformulars ihrer Datenbank zur Bestellabwicklung ein. Die Datenbank findet den Kunden nicht. \"W&uuml;rden Sie den Namen bitte buchstabieren\" - \"K-A-C-S-M-A-R-E-K\" - \"Mit C-S\" - \"Ja, genau!\" Ein Gl&uuml;ck, dass Herr Kacsmarek nicht mit \"Kaufmann-Anton-C&auml;sar-Samuel-Martha-...\" antwortete, denn dann h&auml;tte Frau Meyer wahrscheinlich nochmals nachgefragt ...","og_url":"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-22T22:06:40+00:00","og_image":[{"url":"http:\/\/vg06.met.vgwort.de\/na\/c493928b7cec4a60a4a8fda88b8c459a","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"22\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Fehlertolerantes Suchen","datePublished":"2020-05-22T22:06:40+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/"},"wordCount":4281,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/#primaryimage"},"thumbnailUrl":"http:\/\/vg06.met.vgwort.de\/na\/c493928b7cec4a60a4a8fda88b8c459a","articleSection":["2010","4\/2010","VBA und Programmiertechniken"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/","url":"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/","name":"Fehlertolerantes Suchen - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/#primaryimage"},"thumbnailUrl":"http:\/\/vg06.met.vgwort.de\/na\/c493928b7cec4a60a4a8fda88b8c459a","datePublished":"2020-05-22T22:06:40+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/#primaryimage","url":"http:\/\/vg06.met.vgwort.de\/na\/c493928b7cec4a60a4a8fda88b8c459a","contentUrl":"http:\/\/vg06.met.vgwort.de\/na\/c493928b7cec4a60a4a8fda88b8c459a"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Fehlertolerantes_Suchen\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Fehlertolerantes Suchen"}]},{"@type":"WebSite","@id":"https:\/\/access-im-unternehmen.de\/#website","url":"https:\/\/access-im-unternehmen.de\/","name":"Access im Unternehmen","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access","publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/access-im-unternehmen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/access-im-unternehmen.de\/#organization","name":"Andr\u00e9 Minhorst Verlag","url":"https:\/\/access-im-unternehmen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/","url":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","contentUrl":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","width":370,"height":111,"caption":"Andr\u00e9 Minhorst Verlag"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","caption":"Andr\u00e9 Minhorst"}}]}},"_links":{"self":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000733","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/comments?post=55000733"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000733\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000733"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000733"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000733"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}