Sebastian Goertz: JOIN-Abfrage optimieren

Hallo zusammen,

ich grübel derzeit über eine Datenbankabfrage und komme zu keinem (zufriedenstellenden Ergebnis).

Ich verwende MySQL 5.

Ich habe zwei Tabellen: 'user' und 'geodata'
In 'user' sind Benutzerdaten inkl. 'plz' gespeichert, in 'geodata' finden sich Koordinaten zu bekannten PLZ und PLZ-Bereichen.
Nun wird dem Benutzer nicht verboten, eine nicht bekannte PLZ anzugeben (soll auch nicht, denn ich habe Postfächer/Großkunden/etc. nicht in der Datenbank). Bei der Abfrage muss also die nächsthöhere PLZ ausgegeben werden, wenn die angegebene nicht gefunden wird.

Die einfache Abfrage ist nicht schwer und funktioniert:

SELECT user.*, geodata.x, geodata.y, geodata.z  
FROM user  
LEFT JOIN geodata ON geodata.plz>=user.plz  
WHERE user.id='$id'  
LIMIT 0,1

Jetzt möchte ich mir aber eine Liste von mehreren Einträgen ausgeben lassen. Hier komme ich nicht weiter. Eine Anfrage habe ich probiert, diese funktioniert auch, aber sie braucht aufgrund der hohen Anzahl an Datensätzen in der 'geodata' sehr lange (>30sek für 2 User):

SELECT user.*, geodata.x, geodata.y, geodata.z  
FROM user  
LEFT JOIN geodata ON geodata.plz = (SELECT plz FROM geodata WHERE plz>=user.plz LIMIT 0,1)  
LIMIT 0,2

Welche Möglichkeiten habe ich, diese Anfrage besser zu gestalten? Mein Lösungsansatz wäre eigentlich der, dass ich die einfache Anfrage nutze und eine Möglichkeit finde, das JOIN-Ergebnis zu begrenzen. Nur habe ich keine Hinweise finden können, wie das geht.

Viele Grüße,
Sebastian

  1. Moin!

    SELECT ... where plz > $PLZ ORDER BY plz  LIMIT 1

    MFFG (Mit freundlich- friedfertigem Grinsen)

    fastix

    1. Hallo,

      SELECT ... where plz > $PLZ ORDER BY plz  LIMIT 1

      Was soll das bringen, außer dass - sofern vorhanden - die eigene korrekte PLZ nicht mehr ausgegeben wird?
      Abgesehen davon: die einfache Abfrage eines einzelnen Users habe ich gelöst, es geht darum, eine Liste von mehreren Usern auszugeben...

      Grüße,
      Sebastian

  2. Hallo,

    Jetzt möchte ich mir aber eine Liste von mehreren Einträgen ausgeben lassen. Hier komme ich nicht weiter. Eine Anfrage habe ich probiert, diese funktioniert auch, aber sie braucht aufgrund der hohen Anzahl an Datensätzen in der 'geodata' sehr lange (>30sek für 2 User):

    SELECT user.*, geodata.x, geodata.y, geodata.z

    FROM user
    LEFT JOIN geodata ON geodata.plz = (SELECT plz FROM geodata WHERE plz>=user.plz LIMIT 0,1)
    LIMIT 0,2

      
    
    > Welche Möglichkeiten habe ich, diese Anfrage besser zu gestalten?  
      
    lass Dir [erklären](http://dev.mysql.com/doc/refman/5.1/en/explain.html), ob LIMIT hier sinnvoll ist.  
    Lass Dir erklären, wo [Optimierungsmöglichkeiten](http://dev.mysql.com/doc/refman/5.1/en/optimization.html) vorhanden sind.  
    Überlege Dir gegebenenfalls einen anderen Ansatz.  
      
      
    Freundliche Grüße  
      
    Vinzenz
    
    1. Hi,

      Jetzt möchte ich mir aber eine Liste von mehreren Einträgen ausgeben lassen. Hier komme ich nicht weiter. Eine Anfrage habe ich probiert, diese funktioniert auch, aber sie braucht aufgrund der hohen Anzahl an Datensätzen in der 'geodata' sehr lange (>30sek für 2 User):

      [code lang=sql]SELECT user.*, geodata.x, geodata.y, geodata.z
      FROM user
      LEFT JOIN geodata ON geodata.plz = (SELECT plz FROM geodata WHERE plz>=user.plz LIMIT 0,1)

      wäre es im inneren Select nicht günstiger, mit min zu arbeiten?

      SELECT MIN(plz) FROM geodata WHERE plz >= user.plz

      Abgesehen davon halte ich das Verfahren, einfach die nächsthöhere Postleitzahl zu benutzen, für fragwürdig.

      Beispiel:
      soweit ich rausfinden konnte, ist 79874 Breitnau/Schwarzwald die höchste Normal-PLZ (Normal = Nicht-Großkunde, Nicht-Postfach, ...).
      Die nächsthöhere Normal-PLZ ist dann irgendwas aus dem 80er Bereich - also München. Entfernung über 250km.
      Und spätestens beim 99er Bereich scheitert das Verfahren dann am Vorhandensein höherer PLZ ...

      cu,
      Andreas

      --
      Warum nennt sich Andreas hier MudGuard?
      O o ostern ...
      Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
      1. Hallo,

        wäre es im inneren Select nicht günstiger, mit min zu arbeiten?

        SELECT MIN(plz) FROM geodata WHERE plz >= user.plz

        Das war auch mein erster Ansatz, hat aber keinen (nennenswerten) Unterschied gebracht. Eher noch brauchte diese Anfrage deutlich länger bis zum Ergebnis.

        Abgesehen davon halte ich das Verfahren, einfach die nächsthöhere Postleitzahl zu benutzen, für fragwürdig.

        Habe gelesen, das sei die gängige Praxis. Allerdings könnte ich die Abfrage auch anders gestalten. Ohnehin habe ich "Durchschnittswerte" erzeugt für alle übergeordneten PLZ-Bereiche (also bsp. 44 für 44???). Neuer Ansatz wäre demnach, die letzte Ziffer zu streichen, sollte die angegebene PLZ nicht gefunden werden. Eine Entsprechende CASE-Anweisung konnte ich auch bereits zusamenbasteln, aber wieder tritt meine Problematik auf. Ebenso versuchte ich es mit verschaltelten IF's bzw. XOR...

        Kann ich nicht "einfach" die LEFT JOIN Abfrage auf ein Ergebnis begrenzen ohne dort ein verschachteltes SELECT einbauen zu müssen?

        Grüße,
        Sebastian

        PS: Die Anweisung sähe derzeit (fehlerhaft) so bei mir aus:

        SELECT user.*, geodata.x, geodata.y, geodata.z  
        FROM user  
        LEFT JOIN geodata ON geodata.plz =  
        CASE user.plz WHEN geodata.plz THEN user.plz  
        WHEN SUBSTR(user.plz,1,CHAR_LENGTH(user.plz)-1) THEN SUBSTR(user.plz,1,CHAR_LENGTH(user.plz)-1)  
        WHEN SUBSTR(user.plz,1,CHAR_LENGTH(user.plz)-2) THEN SUBSTR(user.plz,1,CHAR_LENGTH(user.plz)-2)  
        WHEN SUBSTR(user.plz,1,CHAR_LENGTH(user.plz)-3) THEN SUBSTR(user.plz,1,CHAR_LENGTH(user.plz)-3)  
        WHEN SUBSTR(user.plz,1,CHAR_LENGTH(user.plz)-4) THEN SUBSTR(user.plz,1,CHAR_LENGTH(user.plz)-4)  
        END  
        LIMIT 0,2
        
  3. moin,

    was du willst ist kein OUTER JOIN, schließlich willst du zu jeder plz in der user tabelle einen entsprechenden datensatz aus der geodata tabelle. wenn überhaupt, dann ist das ein INNER JOIN. aber es gibt auch so unterschiede zwischen den beiden abfragen. die erste schränkst du in der where klausel schon ein, in der zweiten abfrage machst du das aber nicht, sondern grenzt nur über das limit ein. dadurch geht er erst mal alle datensätze in der user tabelle durch,selbst wenn du nur zwei datensätze daraus haben willst.

    außerdem kann die zweite abfrage gar nicht funktionieren, in der unterabfrage wird nicht sortiert, sprich du nimmst irgend einen datensatz, der größer oder gleich der user.plz ist. du musst es entweder erst sortieren und dann mit limit einschränken oder aber du bentuzt doch  die MIN() aggregat-funktion (vielleicht sortiert mysql dort per default, würde mich aber wundern).

    aber bevor man eine besserung lösung ermittelt, würdemich erst mal interessieren, ob du diese liste an users vorher schon in der hand oder ob es zufällig ausgewählt werden soll. grundsätzlich macht es nämlich erst mal inn, die tabelle der user datensätze auf die anzahl der user zu begrenzen, die du haben willst, bevor es weiter geht.

    Ilja

    1. Hallo,

      was du willst ist kein OUTER JOIN, schließlich willst du zu jeder plz in der user tabelle einen entsprechenden datensatz aus der geodata tabelle. wenn überhaupt, dann ist das ein INNER JOIN.

      Nein, 'plz' ist keine Pflichtangabe und kann 'null' sein. Deshalb kann ich auch kein INNER JOIN draus machen, denn ich möchte alle betroffenen user ausgeben und nicht nur die, welche eine 'plz' angegeben haben.

      du musst es entweder erst sortieren und dann mit limit einschränken

      Ist richtig, hier fehlt das ORDER BY plz ASC. Ändert aber leider nichts an der ewig langen Abfragedauer. Wenn die angegebene 'plz' im niedrigen Bereich ist, muss immernoch fast die ganze 'geodata' abgefragt werden, um den MIN() zu errechnen.
      Aber wie du in meiner Antwort auf MudGuards Beitrag entnehmen kannst, wurde das Konzept nun ohnehin geändert. Ich möchte nun einen übergeordneten Bereich heraussuchen (was auch das gesamte Abfragen und Ermitteln des MIN() erübrigt).

      Mittlerweile habe ich eine Abfrage zusammengeschrieben, welche (endlich) das gewünschte Ergebnis ausgibt:

      SELECT user.*, geodata.x, geodata.y, geodata.z  
      FROM user  
      LEFT JOIN geodata ON geodata.plz = (  
      IF (@a:=(SELECT plz FROM geodata WHERE plz=user.plz),@a,  
      IF (@b:=(SELECT plz FROM geodata WHERE plz=SUBSTR(user.plz,1,CHAR_LENGTH(user.plz)-1)),@b,  
      IF (@c:=(SELECT plz FROM geodata WHERE plz=SUBSTR(user.plz,1,CHAR_LENGTH(user.plz)-2)),@c,  
      IF (@d:=(SELECT plz FROM geodata WHERE plz=SUBSTR(user.plz,1,CHAR_LENGTH(user.plz)-3)),@d,  
      IF (@e:=(SELECT plz FROM geodata WHERE plz=SUBSTR(user.plz,1,CHAR_LENGTH(user.plz)-4)),@e,null)))))  
      )  
      ORDER BY ID ASC LIMIT 0,2
      

      Dieses Codeschnipsel gibt nun die Daten für die ersten zwei user aus (als Beispiel) und sucht die entsprechenden Koordinaten zur PLZ. Existiert die PLZ nicht, wird nach einer übergeordneten gesucht (aus 12345 wird 1234). Existiert auch diese nicht, wirds dreistellig, usw.

      Problem: Auch diese Abfrage bedarf wieder > 30sek bei gerademal zwei Usern von denen nur eine PLZ fehlerhaft ist. Das ist zu lang für einen Praxiseinsatz... Ideen?

      Vielen Dank und Grüße,
      Sebastian.

      1. moin,

        Nein, 'plz' ist keine Pflichtangabe und kann 'null' sein. Deshalb kann ich auch kein INNER JOIN draus machen, denn ich möchte alle betroffenen user ausgeben und nicht nur die, welche eine 'plz' angegeben haben.

        du willst einen INNER JOIN, du willst ja gar keine NULL werte ausgeben, sondern eben falls die plz nicht in der geodaten tabelle vorhanden ist, suchst du einen anderen "partner". das ist doch dein ziel oder habe ich das falsch verstanden ?

        Problem: Auch diese Abfrage bedarf wieder > 30sek bei gerademal zwei Usern von denen nur eine PLZ fehlerhaft ist. Das ist zu lang für einen Praxiseinsatz... Ideen?

        ja, aber es wäre hilfreich, wenn ich die information von dir haben könnte, ob du diese zwei user vor der abfrage in der hand hast.

        Ilja

        1. Hallo,

          du willst einen INNER JOIN, du willst ja gar keine NULL werte ausgeben, sondern eben falls die plz nicht in der geodaten tabelle vorhanden ist, suchst du einen anderen "partner". das ist doch dein ziel oder habe ich das falsch verstanden ?

          Bis auf einen kleinen Punkt: Die plz des Users darf eben auch '' sein, in dem Fall werden natürlich keine Geodaten ausgelesen. Oder anders:
          IF (plz != '') { IF (plz in geodata) { gib geodata } else { gib alternative geodata } }

          ja, aber es wäre hilfreich, wenn ich die information von dir haben könnte, ob du diese zwei user vor der abfrage in der hand hast.

          Die user selbst habe ich nicht "in der hand" ich möchte sie anhand bestimmter Kriterien auflisten. Abgesehen vom geo-data Kram sähe eine Abfrage ungefähr so aus:
          SELECT * FROM user ORDER BY eigenschaft DESC LIMIT 0,15
          Je nach Abfrage ggf. noch ein WHERE rein...

          Ich hoffe das ist das, was du wissen wolltest.

          VG,
          Sebastian

          1. moin,

            Bis auf einen kleinen Punkt: Die plz des Users darf eben auch '' sein, in dem Fall werden natürlich keine Geodaten ausgelesen. Oder anders:
            IF (plz != '') { IF (plz in geodata) { gib geodata } else { gib alternative geodata } }

            zum einen musst man sich bewußt sein, dass in einigen DBMS ein leerstring mit '' nicht NULL entspricht. zum anderen selbst für den leerstring willst du keinen OUTER JOIN, es ist wenn überhaupt ein INNER JOIN und eventuell läßt es sich anders als mit einem JOIN lösen. aber vergiss mal den ansatz mit dem LEFT JOIN.

            das andere problem, dass du hast ist, du musst dir gedanken machen, was du als alternativ wert anzeigen willst. größer oder gleich reicht nämlich nicht für alle fälle aus. stell dir mal vor die geodatenbank ist leer oder aber es gibt keinen größeren alternativ wert als die gesuchte plz, zumal man immer im kopf haben sollte, dass plz keine zahl, sondern ein string ist.

            SELECT * FROM user ORDER BY eigenschaft DESC LIMIT 0,15
            Je nach Abfrage ggf. noch ein WHERE rein...

            bei diesem ansatz muss das dbms alle datensätze der user tabelle durchgehen, um letztlich nur 15 datensätze zu bekommen.

            Ilja

            1. Hallo,

              zum einen musst man sich bewußt sein, dass in einigen DBMS ein leerstring mit '' nicht NULL entspricht. zum anderen selbst für den leerstring willst du keinen OUTER JOIN, es ist wenn überhaupt ein INNER JOIN und eventuell läßt es sich anders als mit einem JOIN lösen. aber vergiss mal den ansatz mit dem LEFT JOIN.

              Bin ich denn jetzt vollkommen auf dem Holzweg? Ein INNER JOIN liefert mir doch nur die Datensätze, zu denen auch entsprechende Ergebnisse aus dem JOIN gefunden werden. In meinem Fall würden also nur die Datensätze ausgegeben, zu deren plz auch koordinaten aufzufinden sind.
              Aber ich möchte doch alle datensätze ausgeben, selbst wenn plz='' und somit keine koordinaten zu finden sind.

              das andere problem, dass du hast ist, du musst dir gedanken machen, was du als alternativ wert anzeigen willst. größer oder gleich reicht nämlich nicht für alle fälle aus. stell dir mal vor die geodatenbank ist leer oder aber es gibt keinen größeren alternativ wert als die gesuchte plz, zumal man immer im kopf haben sollte, dass plz keine zahl, sondern ein string ist.

              Bedenke bitte meinen neuen Ansatz mit SUBSTR. Spätestens die einstelligen Werte sind in der Tabelle (also 0..9).

              SELECT * FROM user ORDER BY eigenschaft DESC LIMIT 0,15
              bei diesem ansatz muss das dbms alle datensätze der user tabelle durchgehen, um letztlich nur 15 datensätze zu bekommen.

              Ging bisher davon aus, dass die Abfrage nach 15 Ergebnissen dann abbricht. Wozu ist dann das LIMIT gut...
              Gibt es bessere/geeignetere Abfragen?

              Viele Grüße,
              Sebastian

              1. Hi!

                SELECT * FROM user ORDER BY eigenschaft DESC LIMIT 0,15
                bei diesem ansatz muss das dbms alle datensätze der user tabelle durchgehen, um letztlich nur 15 datensätze zu bekommen.
                Ging bisher davon aus, dass die Abfrage nach 15 Ergebnissen dann abbricht. Wozu ist dann das LIMIT gut...

                Unter bestimmten Umständen kann MySQL das. Dazu muss ein passender Index vorhanden sein, über den die Daten bereits sortiert abgegriffen werden können. Ansonsten muss erst die gesamte Datenmenge geholt und sortiert werden, bevor man weiß, welches die ersten 15 der sortierten Menge sind. (Nachzulesen - wenn ich mich recht erinnere - im Kapitel zur Optimierung.)

                Lo!

                1. Hallo,

                  SELECT * FROM user ORDER BY eigenschaft DESC LIMIT 0,15
                  bei diesem ansatz muss das dbms alle datensätze der user tabelle durchgehen, um letztlich nur 15 datensätze zu bekommen.
                  Ging bisher davon aus, dass die Abfrage nach 15 Ergebnissen dann abbricht. Wozu ist dann das LIMIT gut...

                  das fragte ich *Dich* schon zu Beginn.
                  Ich wies Dich darauf hin, dass Du Dir den Ausführungsplan besorgen solltest. Dieser zeigt Dir an, ob eine LIMIT-Optimierung stattfindet.

                  Zu raten, was passiert, ist die denkbar schlechteste Idee, um eine Optimierung vorzunehmen. Finde es heraus.

                  Aber warum besorgst Du Dir nicht im *ersten* Schritt Deine zwei (oder auch 15) user-Datensätze, *bevor* Du Dir die Details zu diesen besorgst (sei es über einen Join oder eine Subquery). Verhindere, dass es zu einem riesigen kartesischen Produkt aller Datensätze aus beiden Tabellen kommt, nur um Dir die Details von einer Handvoll anzusehen.

                  Freundliche Grüße

                  Vinzenz

                  1. moin,

                    Ich wies Dich darauf hin, dass Du Dir den Ausführungsplan besorgen solltest. Dieser zeigt Dir an, ob eine LIMIT-Optimierung stattfindet.

                    ich glaube, es ist noch zu früh über tuning zu sprechen, wenn die fachlickeiten noch unklar sind und das sind sie für mich noch. grnudsätzlich gilt zu klären, wie die user datensätze zu mappen sind, für die es keine plz in der geodatenbank gibt. und selbst dort stellt sich mir noch die frage, ob es nur einen datensatz dafür zurück gibt oder sogar mehrfach die gleiche plz in der geodaten tabelle stehen kann (gibt es auf der plz in der geodatenbank einen unique index ?).

                    auf jeden fall ist der ansatz mit dem SUBSTRING nicht vollstänig zu ende gedacht, weil man dort auf jeden fall mehrere geodatensätze für einen user datensatz zurück bekommen kann und somit auch unterschiedliche geodaten. es bleibt also noch die frage offen, wie man die plz ohne partner mappen will, so dass es eine eindeutige zuorndung gibt und dazu noch grenzfälle wie wenn die geodatenbank leer ist, wie die '' bzw. NULL fälle behandelt werden sollen.....

                    Ilja

                    1. Hallo,

                      moin,

                      Ich wies Dich darauf hin, dass Du Dir den Ausführungsplan besorgen solltest. Dieser zeigt Dir an, ob eine LIMIT-Optimierung stattfindet.

                      Was dies angeht, werde ich meine Hausaufgaben machen und mir das/die Kapitel zu Gemüte führen, sobald ich die Ruhe und Muße dazu finde. Unabhängig davon scheinen sich aber noch andere Punkte gezeigt haben (oder irre ich da?):

                      ich glaube, es ist noch zu früh über tuning zu sprechen, wenn die fachlickeiten noch unklar sind und das sind sie für mich noch. grnudsätzlich gilt zu klären, wie die user datensätze zu mappen sind, für die es keine plz in der geodatenbank gibt. und selbst dort stellt sich mir noch die frage, ob es nur einen datensatz dafür zurück gibt oder sogar mehrfach die gleiche plz in der geodaten tabelle stehen kann (gibt es auf der plz in der geodatenbank einen unique index ?).

                      Die Abfrage mit den "IF (@..", welche ich erstellt hatte, liefert mir exakt das Ergebnis, welches ich gern hätte. Nämlich:

                      1. Die Koordinaten, welche zu genau der plz gehören, die der user hat
                      2. Die Koordinaten zu der 4stellig übergeordneten plz, falls 1) nicht existiert
                      3. ...
                      4. ...
                      5. Die Koordinaten zu der 1stellig übergeordneten plz, falls 4) nicht existiert
                      6. null, falls 5) nicht existiert bzw. der user keine plz angegeben hat

                      Rahmenbedingungen:

                      • unique index auf geodata.plz [char(5)]
                      • es existieren alle 1stelligen übergeordneten plz 0..9
                      • user.plz ist nicht NULL sondern '' oder eben bis zu 5 ziffern

                      Bemerkung:
                      Ich sehe bei dieser Aufstellung direkt ein, dass 6) an erster Stelle gehört, also zunächst geprüft werden soll, ob der user überhaupt eine plz hat oder plz='' ist. Ändert aber mein Problem noch nicht, dass die Abfrage zu lang dauert, sobald user.plz nicht unmittelbar seinen Pendant in geodata.plz hat.

                      auf jeden fall ist der ansatz mit dem SUBSTRING nicht vollstänig zu ende gedacht, weil man dort auf jeden fall mehrere geodatensätze für einen user datensatz zurück bekommen kann und somit auch unterschiedliche geodaten.

                      Wieso? Mit den IF-Anweisungen bekomme ich nur ein Ergebnis, weil der jeweils folgende SUBSTR... nur ausgeführt wird, wenn bisher noch nichts gefunden wurde.

                      -----

                      Vereinbarung meinerseits:
                      Wenn ich die Sache in den Griff bekommen sollte, nachdem ich meine oben genannten Hausaufgaben gemacht habe, dann können wir Thematik hier vorerst beenden. Dafür ist mir eure Zeit zu kostbar.
                      Gibt es aber tatsächlich noch andere Knackpunkte, die mir das Kapitel OPTIMIZATION nicht löst, bin ich für jeden Hinweis dankbar :-)

                      Viele Grüße,
                      Sebastian

                      1. moin,

                        Die Abfrage mit den "IF (@..", welche ich erstellt hatte, liefert mir exakt das Ergebnis, welches ich gern hätte.

                        diese aussage kann ich nicht nachvollziehen. nehmen wir mal den fall du hast einen user, dessen 5 stellige plz (beispiel 12345) nicht trifft. in der geo tabelle sind folgende plz enthalten:

                        12346
                        12347
                        12348

                        dann trifft doch die vierstellige plz 1234 auf mehr als einen datensatz in der geo tabelle oder sehe ich jetzt was verkehrt ? gib mal beispiel, damit ich mir ein bild davon machen kann.

                        • unique index auf geodata.plz [char(5)]

                        und das sagt mir, dass es nur 5 stellige plz in der geo tabelle gibt.

                        Ilja

                        1. Hallo,

                          dann trifft doch die vierstellige plz 1234 auf mehr als einen datensatz in der geo tabelle oder sehe ich jetzt was verkehrt ? gib mal beispiel, damit ich mir ein bild davon machen kann.

                          Aaaah, das "Missverständnis" liegt bei meiner Wortwahl bzgl. der übergeordneten PLZ. In der geodata finden sich plz wie:

                          1. alle regulär vergebenen 5stelligen PLZ
                          2. 4stellige "Durchschnitts-PLZ", sofern es damit beginnende 1) gibt
                          3. 3stellige ..., sofern es ... 2) gibt
                          4. 2stellige ..., sofern es ... 3) gibt
                          5. 1stellige ..., sofern es ... 4) gibt

                          Aus 1) bis 4) folgt, dass die Werte '0', '1', ..., '9' in der Tabelle als Werte für plz enthalten sind.

                          Beispiele dafür:
                          zu 1) 01067, 10115, 10117, 10119 existieren in geodata.plz
                          zu 1) 01030, 01031, ..., 01039 existieren nicht in geodata.plz

                          zu 2) 0106, 1011 existieren / 0103 existiert nicht
                          zu 3) 010, 101 existieren (hier fünde 01038 sein Pendant 010)
                          zu 4) 01, 10
                          zu 5) 0, 1

                          • unique index auf geodata.plz [char(5)]
                            und das sagt mir, dass es nur 5 stellige plz in der geo tabelle gibt.

                          Wäre hier varchar(5) angebrachter?
                          Als Integer speichern kommt nicht in Frage, da es zu Fehlern käme: PLZ '01067' würde genauso gespeichert wie '1067' (=1067*)

                          Viele Grüße,
                          Sebastian