Announcement

Collapse
No announcement yet.

Komplexe Suche in Adressdatenbank

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Komplexe Suche in Adressdatenbank

    Ich habe eine knifflige Aufgabe: In einem Datenbankprojekt gibt es normalisierte Tabellen mit Orten, Ortsteilen, Straßen und den Häusern in den Straßen (inkl. Hausname, z.B. "Krankenhaus"). Per Joins kann ich die Daten praktisch zu kompletten Adressen zusammenstellen.
    <br>
    Bisher hat man eine Adresse im Programm gesucht über Auswahl von Ort und Ortsteil und anschließendem Tippen einiger Buchstaben des Straßen- oder Häusernamens. Ich muss aber jetzt eine Möglichkeit schaffen, dass der Benutzer mit nur einem Suchfeld auskommt.
    <br>
    <b>Beispiel:</b>
    <br>
    Ort: Berchtesgaden
    Ortsteil: Markt
    Straße: Bergwerkstraße 42
    Objekt: Feuerwehrhaus
    <br>
    Ich soll jetzt ermöglichen, dass dieses Objekt z.B. durch Eingabe von "bercht bergwerk 42" oder "berchtesg feuerwehr" oder "berc bergwerk feuer markt" usw... gefunden wird, bzw. eine Auswahlliste der noch passenden Datensätze mit jedem getippten Buchstaben (bzw. jedem getippten Fragment) kürzer wird.
    <br>
    Wie mache ich so etwas? Die Reihenfolge der eingegebenen Fragmente soll zudem völlig frei sein!
    <br>
    Bin echt über jeden Vorschlag und jede Hilfe dankbar!
    Thomas

  • #2
    Hallo, <br>

    wie wäre es mit einem weiteren Feld in der Tabelle?<br>
    Über einen Trigger füllst Du dieses Feld mit allen Inhalten,
    über die gesucht werden soll. Also Ort+Ortsteil+Straße+
    Objekt. Mit 'Lowercase' alles klein.<br>
    Dann kann über eine entsprechende Abfrage mit
    'Containing' nach den Begriffen gesucht werden.

    Gruß<Br>
    Hors

    Comment


    • #3
      Ich habe leider nicht die volle Kontrolle / Macht über die Datenstruktur. Hinzu kommt, dass für manche Orte sehr wohl Straßen, jedoch keine Häuser- und Objektdaten hinterlegt sind (das LEFT OUTER JOIN bringt Null-Werte).

      Zudem bin ich mir nicht sicher, ob es das Containing auch bei Interbase gibt und wenn ja, ob es auch mit Fragmenten arbeitet?

      Ich hätte jetzt eher daran gedacht, ein Statement mit LIKE, UPPERCASE, AND und OR entsprechend dynamisch zu basteln, wobei vorher z.B. bereits abgeprüft wird, ob numerische Eingaben sind, damit diese nur auf das Hausnummern-Feld angewendet werden.

      Irgendwelche andere Ideen?

      Die Anwender können sich sicher nicht vorstellen, was es bedeutet mal eben nur eine "Eingabe in EINEM Suchfeld anstelle der bisherigen Suchmaske" zu realisieren... ;-)

      Danke und Gruss
      Thoma

      Comment


      • #4
        Hallo Thomas,
        ich denke mal ohne Kontrolle über die Datenstrukturen und das Anlegen entsprechender Suchfelder oder Suchtabelle wird es nicht gehen.
        <cite>
        Ich hätte jetzt eher daran gedacht, ein Statement mit LIKE, UPPERCASE, AND und OR entsprechend dynamisch zu basteln,
        </cite>
        Das wird mit Sicherheit so grottenlangsam (wenn deine Adressdaten nicht nur 100 DS haben , das sich deine Anwender die "bisherige Suchmaske" zurückwünschen. LIKE '%xxx', UPPERCASE und OR führen in aller Regel dazu, das du keine Indizes mehr anlegen brauchst, da sie der Server für diese Suche nicht verwenden kann!

        Einen konkreten Vorschlag, wie so eine Suchtabelle aussehen könnte, hab ich aber auch nicht, da ich meine Anwender bisher immer davon überzeugen konnte "strukturiert" zu suchen

        Gruß Fal
        Wenn du denkst du hast alle Bugs gefunden, dann ist das ein Bug in deiner Denksoftware.

        Quellcode ohne ein Mindestmaß an Formatierung sehe ich mir nicht an! Ich leiste keinen Privatsupport per Mail oder PN!

        Comment


        • #5
          Hallo!
          Also ohne Änderungen der DB geht es nicht....
          Du brauchst eine neue Tabelle, die für die jeweiligen Datensätze alle vorkommenden Worte enthält.
          Worte
          Adessen_id integer
          Wort vachar(irgendwas)
          Jetzt kannst Du die Suche auf diese Tabelle beschränken. Egal welche Worte oder in welcher Reihenfolge Du suchst. Wir haben das in unserer Adressdatenbank so gelöst und das ganze klappt auch bei 300tsd Adressdatensätzen noch gut.
          Wenn Du jetzt in diese Tabelle noch eine weitere Spalte mit dem phonetischen Lautwort (z.B. Soundex) einsetzt bekommst Du eine schicke Suche, die Tippfähller ausgleicht.

          BYE BERN

          Comment


          • #6
            Hallo,

            unter Interbase, Firebird gibt es Containing. Diese ist sehr schnell und ignoriert auch die Groß/Kleinschreibung.

            Bern

            Comment


            • #7
              Hallo Thomas,

              wenn es Dir hilft, könnte ich Dir eine Funktion anbieten, die zwei Zeichenketten auf Ähnlichkeiten untersucht und bewertet (0..100%). Dabei spielen die Reihenfolge der Wörter nur eine untergeordnete Rolle.
              Also Deine o.g. Beispiele würde sie sicherlich finden. Und wenn in den Suchbegriffen "Marktplatz" stehen würde, würde das nur zu einer geringen Abwertung der Ähnlichkeitsquote führen.

              Bei Deinem Problem mit einem zusätzlichen Feld oder einer zusätzliche Tabelle hilft das natürlich nicht weiter. Den Ähnlichkeitswert kannst Du nur zeilenweise (per Delphi,
              nicht per SQL natürlich) zuordnen und die Ergebnisse dann absteigend sortiert ausgeben. In einem eigenen Thread wäre sicher sinnvoll.

              Falls Du Interesse an der Funktion hast, schreib an [email protected]

              Gruß Stahl

              Comment


              • #8
                @André
                Auf welchem Algorithmus basiert der Vergleich?
                BYE BERN

                Comment


                • #9
                  Hallo Thomas,

                  wenn es Dir hilft, könnte ich Dir eine Funktion anbieten, die zwei Zeichenketten auf Ähnlichkeiten untersucht und bewertet (0..100%). Dabei spielen die Reihenfolge der Wörter nur eine untergeordnete Rolle.
                  Also Deine o.g. Beispiele würde sie sicherlich finden. Und wenn in den Suchbegriffen "Marktplatz" stehen würde, würde das nur zu einer geringen Abwertung der Ähnlichkeitsquote führen.

                  Bei Deinem Problem mit einem zusätzlichen Feld oder einer zusätzliche Tabelle hilft das natürlich nicht weiter. Den Ähnlichkeitswert kannst Du nur zeilenweise (per Delphi,
                  nicht per SQL natürlich) zuordnen und die Ergebnisse dann absteigend sortiert ausgeben. In einem eigenen Thread wäre sicher sinnvoll.

                  Falls Du Interesse an der Funktion hast, schreib an [email protected]

                  Gruß Stahl

                  Comment


                  • #10
                    @Bernd: Auf meinem eigenen ;-))

                    Es werden die Umlaute in normale Buchstaben umgewandelt und dann alle Zeichen außer Buchstaben und Ziffern entfernt. Dann werden die längstmöglichen Übereinstimmenden Zeichenfolgen gesucht, bewertet und entfernt (je länger, je lieber).
                    Die zu vergleichenden Abschnitte werden dann immer weiter verkürzt. Kürzere Abschnitte erhalten eine niedrigere Bewertung.

                    "Karl-Heinz Müller" wird zu "Müller, Karlheinz" als sehr ähnlich bewertet. "ABC-GmbH Halle" zu "a.b.c gmbh (Halle)" sogar als 100%ig gleich.

                    Ich selbst habe die Adressen noch in Vor- und Nach- "c/o-Abschnitte" untergliedert und getrennt verglichen. So finde ich Kunden, die auch als "c/o" aufgenommen wurden.

                    Ich bin mit den Ergebnissen ganz zufrieden...

                    Gruß Stahl

                    Comment


                    • #11
                      Hallo,

                      wie wäre es wenn man einfach die einzelnen Tabellen nacheinander durchsucht bspw. mit dieser Ähnlichkeit. Man erhält dann Zahlen (die ID-Nummern) und die sucht man dann in der nächst höheren Tabelle und hangelt sich so von unten nach oben. Dann kann man auch die mit mehreren Treffern zuerst anzeigen wie in einer Web-Suchmaschine.
                      Das Ergebnis zeigt man dann in einer Kopie (bspw. Clientdataset oder einer Memory-Tabelle).
                      Ich weis aber nicht ob das nicht evtl. zu lange dauert. Müsste man mal testen.
                      Gruß Matthia

                      Comment


                      • #12
                        Hallo Matthias,

                        das dauert natürlich etwas. Bei uns (DBase, BDE) bei 45000 Adressen ca. 20 Sekunden, allerdings auch mit ständiger Zwischenstandanzeige. Man kann sicher das ganze optimieren und bei Programmstart alle Adressen einmalig in den Speicher (StringList oder ClientDataSet) laden, dann geht´s noch wesentlich schneller.

                        Wenn man die Suche in einem eigenen Thread laufen lässt, könnte man sie sicherlich bei jedem Tastendruck abbrechen und neu starten lassen (ist aber für mich Neuland). Dann könnte man die Suchbegriffe eintippen und würde parallel dazu bei jeder Änderung eine Liste von möglichen Adressen (sortiert nach Ähnlichkeiten) erhalten..

                        Comment


                        • #13
                          Hallo zusammen,

                          also ich hab jetzt in meiner Not zunächst einmal Tests gemacht, indem ich mir in DElphi eine kleine Unit geschrieben habe, die mir den Suchstring in Tokens zerlegt, und diese anschließend mit Uppercase und LIKE in einen SQL-Suchstring verwandelt. Diesen schicke ich dann an die Datenbank.

                          Ich habe derzeit noch nicht alle Daten des gesamten Landkreises in der Datenbank, aber doch schon mind. 65%, und hier funktioniert die DB-Abfrage auf dem selben Rechner (Local Server) extrem schnell, d.h. ich kann mit jedem weiteren Buchstaben eine neue Suche abschicken, das geht quasi in Echtzeit.

                          Das Verhalten übers Netz muss ich erst noch testen. Etwas umständlich wird es, wenn man in einer Stadt zugleich in drei Stadtteilen eine Straße mit gleichem Namen hat (z.B. eine, die sich durch drei Stadtteile erstreckt). Dann muss man den Straßennamen fast ausschreiben und dann die richtige Straße der drei selbst auswählen oder den Stadtteilnamen dazutippen (Beispiel: Bad Reichenhall mit der Reichenhallerstraße).

                          Im Moment bin ich mit dieser Lösung sehr zufrieden, mal sehen was sich dann ändert, wenn alles drin ist und über Netz geht. Danke für Eure Anregungen und Hilfe!

                          Thoma

                          Comment


                          • #14
                            Hallo!
                            Einen Lösungsansatz, den wir gewählt haben ist erstmal zu prüfen, wieviele Datensätze im Filter wären, BEVOR man die Daten übers Netz sendet. Erst unter einem Schwellwert werden die Daten dann tatsächlich übertragen....
                            BYE BERN

                            Comment

                            Working...
                            X