split.s: mysql: NAHE Ergebnisse

Hey Forum!

Gibt es eigentlich einen Trick oder eine Funktion, anhand derer ich "nahe" Ergebnisse ermitteln kann?

Ein Beispiel:

Beispiel 1:
Ich möchte 10 Geburtstage, die unmittelbar nach,- und vor meinem eigenen liegen, also die 10 NÄHESTEN Geburtstage.

Beispiel 2:
Ich möchte anhand von lat/lon die nähesten 10 Orte ermitteln.

Nun zur Problematik:
Ich brauche unbedingt 10 Ergebnisse. Das heisst, selbst wenn z.B. die nächsten 10 Orte 300 KM entfernt voneinander liegen, so gehören diese trotzdem in die Ergebnistabelle.

Wie könnte man sowas anstellen?

  1. Om nah hoo pez nyeetz, split.s!

    Gibt es eigentlich einen Trick oder eine Funktion, anhand derer ich "nahe" Ergebnisse ermitteln kann?

    Ich brauche unbedingt 10 Ergebnisse. Das heisst, selbst wenn z.B. die nächsten 10 Orte 300 KM entfernt voneinander liegen, so gehören diese trotzdem in die Ergebnistabelle.

    Wie könnte man sowas anstellen?

    Ich würde den Holzhammer nehmen und einfach alle Datensätze suchen, die Ergebnisliste per ORDER BY ordnen und mit LIMIT in der Länge begrenzen.

    Matthias

    --
    1/z ist kein Blatt Papier.

    1. Versteh ich jetzt nicht.
      Wie finde ich denn "die nähesten Geburtstage von 1987-10-10" ?
      Verstehe den Zusammenhang zu ORDER noch nicht so ganz.

      1. Om nah hoo pez nyeetz, split.s!

        Wie finde ich denn "die nähesten Geburtstage von 1987-10-10" ?

        Bilde die Differenz. Wenn die Geburtstage in der Zukunft und in der Vergangenheit liegen, dann noch den Betrag der Differenz.

        ORDER BY ordnet die auszugebenden Datensätze nach einem gewünschten Kriterium.

        Matthias

        --
        1/z ist kein Blatt Papier.

        1. Was für eine Differenz? Ich kann ja keinen Radius vorgeben.

          1. Was für eine Differenz? Ich kann ja keinen Radius vorgeben.

            Aber den Raduis ausrechnen kannst du ja und dann nach dem sortieren.
            Also ORDER BY (Entfernung zwischen Tabelle.Ort und aktuellem Ort)

            Da gibts dann vielleicht schon mal ein Problem mit der Performance, wenn du Millionen Einträge hast und bei jedem die Differenz berechnet werden muss, damit nach dieser sortiert werden kann.
            In diesem Fall könntest du die Koordinaten erst mal beschränken, dass nur Koordinaten in einem bestimmten Bereich verwendet werden. Die findet ein Index (sofern vorhanden) schnell, dann muss nur für diese Datensätze die Differenz berechnet werden.
            Wenn das keine 10 Einträge gibt, änderst du die Einschränkung so um dass mehr Einträge gefunden werden.

          2. Hi,

            Was für eine Differenz? Ich kann ja keinen Radius vorgeben.

            Mit dem Betrag über der Differenz erreichst du genau das.

            Bis die Tage,
            Matti

          3. Tach!

            Was für eine Differenz? Ich kann ja keinen Radius vorgeben.

            Bitte nicht durcheinander fragen. Das Thema war eben der Geburtstag. Was willst du da mit einem Radius? Hast du nun verstanden, wie man die Differenz zweier Tage ermittelt?

            Und nun zur Entfernung. MySQL kennt seit einiger Zeit eine Spacial Extension. Damit können unter anderem geografische Koordinaten gespeichert werden. Eine Funktion zur Ermittlung der Differenz zwischen zwei Punkten ist leider nicht implementiert, aber es gibt einen Workaround, bei dem man eine Linie zu Hilfe nimmt, deren Länge man ermitteln kann. Diese Lösung findest du über die Stichwörter "mysql spacial distance".

            dedlfix.

            1. Hi,

              Was für eine Differenz? Ich kann ja keinen Radius vorgeben.

              Bitte nicht durcheinander fragen. Das Thema war eben der Geburtstag. Was willst du da mit einem Radius? Hast du nun verstanden, wie man die Differenz zweier Tage ermittelt?

              Eine Sphäre (die Verallgemeinerung eines Kreises oder einer Kugel) ist die Menge aller Punkte, die einen festen Abstand r zu einem Punkt z (dem "Mittelpunkt") haben. Der feste Abstand r ist der Radius.
              Auf der Zahlgeraden ist eine Sphäre analog die beiden Punkte, welchen gleichen Abstand zu einem Punkt haben, und das sind gerade x:=z+r und y:=z-r. Es gilt jeweils |y-z| = |x-z| = r. Lange Rede, kurzer Sinn: auch auf der Zahlgeraden gibt es Radien, wobei es sich da im Wesentlichen um das handelt, was du vorher schonmal geschrieben hast.

              Also nochmals: sortieren nach dem Betrag der Differenz und dann das Ergebnis auf die gewünschte Zahl einschränken.

              Ein anderer Denkansatz (und damit mein Posting auch einen wirklichen Sinn hat): MySQL hat ja gewisse Probleme mit Indizes auf berechneten Werten. Man könnte daher mal ausprobieren, die Abfrage aufzuteilen in die Elemente, die größer sind, und diejenigen, die kleiner sind, und beide Abfragen auf n Elemente beschränken (n - gewünschte Zeilenzahl). Die 2n Elemente dann mit der Betrags-Logik behandeln. Nur mal so als Tipp ins Blaue hinein, könnte bei großer Zeilenzahl und kleinem n schneller sein als den Betrag zum Zielwert für alle zu berechnen.

              Bis die Tage,
              Matti

              1. Tach!

                MySQL hat ja gewisse Probleme mit Indizes auf berechneten Werten.

                Ein nicht vorhandenes Feature mag für den Anwender ein Problem sein, aber nicht für das System selbst. Abgesehen davon, welchen berechneten Wert sollte denn der Index speichern, wenn einer der Operanden erst zur Abfragezeit bekannt ist? Du kannst deswegen ja noch nicht einmal eine Spalte mit einem selbst berechneten Wert einfügen. Nur wenn letzteres ginge, wäre auch ein berechneter Index möglich.

                Man könnte daher mal ausprobieren, die Abfrage aufzuteilen in die Elemente, die größer sind, und diejenigen, die kleiner sind, und beide Abfragen auf n Elemente beschränken (n - gewünschte Zeilenzahl). Die 2n Elemente dann mit der Betrags-Logik behandeln. Nur mal so als Tipp ins Blaue hinein, könnte bei großer Zeilenzahl und kleinem n schneller sein als den Betrag zum Zielwert für alle zu berechnen.

                Die Frage ist, ab oder bis zu wieviel Datensätzen ist der eine Ansatz schneller als der andere? Der eine hat den Aufwand alle Datensätze berechnen zu müssen, der andere muss zwei Abfragen laufen lassen und diese sortieren, limitieren und diese dann berechnen.

                dedlfix.

                1. Hi,

                  MySQL hat ja gewisse Probleme mit Indizes auf berechneten Werten.

                  Ein nicht vorhandenes Feature mag für den Anwender ein Problem sein, aber nicht für das System selbst. Abgesehen davon, welchen berechneten Wert sollte denn der Index speichern, wenn einer der Operanden erst zur Abfragezeit bekannt ist? Du kannst deswegen ja noch nicht einmal eine Spalte mit einem selbst berechneten Wert einfügen. Nur wenn letzteres ginge, wäre auch ein berechneter Index möglich.

                  Ich könnte mich rausreden und sagen, dass der OP nicht gesagt hat, dass die Werte nicht dauerhaft konstant wären. Immerhin (auf Beispiel 1 bezogen) wird sein Geburtstag  wohl eher nicht wild im Jahr hin- und herspringen *fg*. Aber du hast natürlich recht.

                  Man könnte daher mal ausprobieren, die Abfrage aufzuteilen in die Elemente, die größer sind, und diejenigen, die kleiner sind, und beide Abfragen auf n Elemente beschränken (n - gewünschte Zeilenzahl). Die 2n Elemente dann mit der Betrags-Logik behandeln. Nur mal so als Tipp ins Blaue hinein, könnte bei großer Zeilenzahl und kleinem n schneller sein als den Betrag zum Zielwert für alle zu berechnen.

                  Die Frage ist, ab oder bis zu wieviel Datensätzen ist der eine Ansatz schneller als der andere? Der eine hat den Aufwand alle Datensätze berechnen zu müssen, der andere muss zwei Abfragen laufen lassen und diese sortieren, limitieren und diese dann berechnen.

                  Eins der Dinge, die ich beim DB-Optimieren gelernt habe: ausprobieren und messen. Deswegen schrieb ich ja auch ausprobieren dazu.

                  Bis die Tage,
                  Matti