Linuchs: SELECT Bahnhöfe auf einer Strecke

Hallo,

ich habe eine Bahnlinie angelegt und die ID der Bahnhöfe (treffpunkte) in einem Textfeld mit Komma getrennt.

Nun möchte ich die Bahnhöfe in der richtigen Reihenfolge auslesen:

SELECT
 lin1.id            LIN
,lin1.titel         lin_titel
,lin1.treffpunkt_ids

,trp1.id            TRP
,trp1.gebaeude_name
,ort1.id            ORT
,ort1.land_kz       ort_land_kz
,ort1.plz           ort_plz
,ort1.name          ort_name
FROM        bia_linien lin1
LEFT JOIN   bia_treffpunkte trp1
#ON          trp1.id IN ( lin1.treffpunkt_ids )
ON          trp1.id IN ( 1171,1170 )
LEFT JOIN   bia_orte ort1
ON          ort1.id    = trp1.ort_id
WHERE       lin1.id = '1'

Die hier mit # ausgeblendete Version bringt nur einen Treffer, obwohl zwei Einträge im Feld lin1.treffpunkt_ids vorhanden sind.

Die dann zwecks Test eingesetzten Treffpunkte bringen zwar zwei Treffer, aber nicht in der richtigen Reihenfolge.

Was mache ich falsch?

Gruß, Linuchs

  1. Hallo Linuchs,

    ich habe eine Bahnlinie angelegt und die ID der Bahnhöfe (treffpunkte) in einem Textfeld mit Komma getrennt.

    Die hier mit # ausgeblendete Version bringt nur einen Treffer, obwohl zwei Einträge im Feld lin1.treffpunkt_ids vorhanden sind.

    Die dann zwecks Test eingesetzten Treffpunkte bringen zwar zwei Treffer, aber nicht in der richtigen Reihenfolge.

    Was mache ich falsch?

    Ich denke, du missachtest hier die Normalisierung. Einträge in DB-Felder müssen atomar sein. MMn. wird dir nichts weiter übrig bleiben als die Treffpunkte mit der Bahnlinie in eine m:n-Beziehung zu stecken.

    Bis demnächst
    Matthias

    --
    Das Geheimnis des Könnens liegt im Wollen. (Giuseppe Mazzini)
    1. Hallo Matthias,

      Ich denke, du missachtest hier die Normalisierung. Einträge in DB-Felder müssen atomar sein. MMn. wird dir nichts weiter übrig bleiben als die Treffpunkte mit der Bahnlinie in eine m:n-Beziehung zu stecken.

      Au weh, eine weitere Tabelle. Die DB wird langsam unübersichtlich.

      Zwar könnte ich dann für jeden Bahnhof / Haltestelle die anderen Linien finden, aber das ist nicht die Aufgabe.

      Nee, da lese ich lieber die Aufzählung aus dem Feld und übergebe sie einem zweiten SELECT.

      Bleibt die Frage, wie ich die vorgegebene Reihenfolge bekommen kann.

      Linuchs

  2. Tach!

    ich habe eine Bahnlinie angelegt und die ID der Bahnhöfe (treffpunkte) in einem Textfeld mit Komma getrennt.

    Soweit so schlecht.

    #ON          trp1.id IN ( lin1.treffpunkt_ids )
    ON          trp1.id IN ( 1171,1170 )
    

    Die hier mit # ausgeblendete Version bringt nur einen Treffer, obwohl zwei Einträge im Feld lin1.treffpunkt_ids vorhanden sind.

    In dem Feld ist ein String. Ein String sind keine zwei Werte, egal wie er aussieht. Der IN()-Operator möchte die Wert direkt haben. Er klamüsert sich die nicht aus einen String heraus.

    Dass du überhaupt einen Treffer bekommst, liegt an der automatischen Typumwandlung, weil trp1.id eine Zahl ist und damit die Typumwandlung in Richtung Zahl veranlasst. Bei "1171,1170" sieht der erste Teil bis zum Komma wie eine Zahl aus. Somit löst sich sinngemäß

    SELECT 1171 IN ("1171,1170")
    

    zu

    SELECT 1171 IN (1171)
    

    auf und ergibt 1 (=true). Gegenproben:

    SELECT "1171" IN ("1171,1170")
    SELECT 1170 IN ("1171,1170")
    

    Das ergibt zum einen 0 (=false), weil die Strings direkt verglichen werden, und zum anderen ebenfalls 0, weil die Typumwandlung 1171 ergibt und das nicht gleich 1170 ist.

    Du kannst zwar FIND_IN_SET() nehmen, aber das bleibt keine gescheite Lösung. Ein RDBMS ist auf Datenmengen optimiert, nicht auf Stringverarbeitung. Für letztere kann es keine Optimierungen verwenden und muss immer den kompletten Datenbestand durchlaufen.

    Die dann zwecks Test eingesetzten Treffpunkte bringen zwar zwei Treffer, aber nicht in der richtigen Reihenfolge.

    Reihenfolge erhält man mit ORDER BY (und unter Umständen auch mit GROUP BY). Alle anderen Mengen sind per Definition unsortiert.

    dedlfix.

    1. Moin!

      habe doch eine weitere Tabelle angelegt, die bei den Treffpunkten pro Bahn -linie auch die Reihenfolge angibt.

      Linuchs

      1. Hallo

        habe doch eine weitere Tabelle angelegt, die bei den Treffpunkten pro Bahn -linie auch die Reihenfolge angibt.

        Das wird dir mit einiger Wahrscheinlichkeit auf die Füße fallen, wenn an einem Bahnhof mehrere Linien bedient werden. Wenn du es genau nimmst, hast du eine Menge von Bahnstationen, eine zweite Menge von Linien und eine dritte Menge von Reihenfolgen der Stationen auf den einzelnen Linien.

        Ob man die Stationen pro Linie durchzählt oder pro Station und Linie angibt, welche Station die Nächste ist, um das zu einem Linienplan zusammenzufassen, sollte hier mal zur Diskussion stehen. Ich weiß auch nicht aus dem Hut, wie man das optimal angeht.

        Tschö, Auge

        PS: „Bahnlinie“ ist ein zusammengesetztes Substantiv.

        --
        Es schimmerte ein Licht am Ende des Tunnels und es stammte von einem Flammenwerfer.
        Terry Pratchett, „Gevatter Tod“
        1. Tach!

          Ob man die Stationen pro Linie durchzählt oder pro Station und Linie angibt, welche Station die Nächste ist, um das zu einem Linienplan zusammenzufassen, sollte hier mal zur Diskussion stehen. Ich weiß auch nicht aus dem Hut, wie man das optimal angeht.

          Das sind also zwei Herangehensweisen. Die eine ist, einen Reihenfolgenwert in ein Feld aufzunehmen. Man kann dann ein einfaches ORDER BY darauf abfeuern und bekommt die Reihenfolge - solange die Werte nicht doppelt vorkommen. Man kann das als Float-Wert implementieren, dann hat man praktisch beliebig viele verwendbare Zwischenwerte. (Theoretisch begrenzt durch die Ungenauigkeit des Float-Formats ab einer bestimmten Stellenanzahl.)

          Die andere ist eine verkettete Liste. Für die wäre es sehr ungünstig, bereits in der Datenbank-Abfrage eine Reihenfolge haben zu müssen. Man kann die Menge nicht per Index sortieren, sondern müsste eine Funktion schreiben. Allerdings weiß man nur beim direkten Nachfolger, dass es selbiger ist. Zwischen zwei beliebigen Stationen kann man ein größer oder kleiner als nur wissen, wenn man die Kette bis zu einem der beiden Elemente +/- Nachfolger abgeklappert hat. Das ist nichts, was man dem DBMS unbedingt aufbürden möchte. Allerdings kann man beim Ausgeben die Liste entlanglaufen und es wird einigermaßen performant, wenn man die nächste Station anhand eines Wertes in einer Hash-Tabelle finden kann. - Problematisch wird es, wenn die Kette warum auch immer unterbrochen wurde. Da ist dann direkt Ende im Gelände. Bei Variante 1 fehlte lediglich nur eine Station.

          dedlfix.

        2. habe doch eine weitere Tabelle angelegt, die bei den Treffpunkten pro Bahn -linie auch die Reihenfolge angibt.

          Das wird dir mit einiger Wahrscheinlichkeit auf die Füße fallen, wenn an einem Bahnhof mehrere Linien bedient werden.

          Wieso?

          Es sind drei Tabellen beteiligt:

          • linien

          • treffpunkte (Bahnhöfe)

          • linien_treffpunkte (mit lfd. Stationsnummer innerhalb der Linie)

          Logisch können mehrere Linien einen oder mehrere gemeinsame Bahnhöfe haben, die kommen dann in der dritten Tabelle mehrfach vor.

          Ob man die Stationen pro Linie durchzählt oder pro Station und Linie angibt, welche Station die Nächste ist, um das zu einem Linienplan zusammenzufassen, sollte hier mal zur Diskussion stehen.

          Was meinst du mit "nächste"? Aus den Entfernungen kann ich aus Sicht eines Bahnhofs nicht erkennen, welche Station zeitlich die nächste ist. Das hängt von der Fahrtrichtung ab.

          Ich gebe den Bahnhöfen der Linie Wiesbaden - Aschaffenburg in der dritten Tabelle die lfd. Nr. 1 bis 20. So kann ich die Reihenfolge sortiert ausgeben. In der anderen Richtung absteigend.

          Problematisch wird es, wenn sich eine "Linie" auffächert, also in der einen Richtung andere Haltestellen anfährt als in der anderen Richtung. Das kommt aber eher bei Bussen vor. Bei Buslinien gibt es dann noch viel mehr Besonderheiten.

          Linuchs

          1. Hallo

            Logisch können mehrere Linien einen oder mehrere gemeinsame Bahnhöfe haben, die kommen dann in der dritten Tabelle mehrfach vor.

            Mal sehen, wie lange es dauert, bis hier jemand nach Normalisierung ruft.

            Ob man die Stationen pro Linie durchzählt oder pro Station und Linie angibt, welche Station die Nächste ist, um das zu einem Linienplan zusammenzufassen, sollte hier mal zur Diskussion stehen.

            Was meinst du mit "nächste"? Aus den Entfernungen kann ich aus Sicht eines Bahnhofs nicht erkennen, welche Station zeitlich die nächste ist. Das hängt von der Fahrtrichtung ab.

            Es gibt benachbarte Stationen, also ist für eine Linie aus der Entfernung erkennbar, welche Station welcher anderen folgt.

            Ich gebe den Bahnhöfen der Linie Wiesbaden - Aschaffenburg in der dritten Tabelle die lfd. Nr. 1 bis 20. So kann ich die Reihenfolge sortiert ausgeben. In der anderen Richtung absteigend.

            Das ist hoffentlich nur eine Frage der Sortierung, falls nicht das Folgende zutrifft.

            Problematisch wird es, wenn sich eine "Linie" auffächert, also in der einen Richtung andere Haltestellen anfährt als in der anderen Richtung.

            Tschö, Auge

            --
            Es schimmerte ein Licht am Ende des Tunnels und es stammte von einem Flammenwerfer.
            Terry Pratchett, „Gevatter Tod“
            1. Hallo Auge,

              mal sehen, wie lange es dauert, bis hier jemand nach Normalisierung ruft.

              - 2,5d

              Bis demnächst
              Matthias

              --
              Das Geheimnis des Könnens liegt im Wollen. (Giuseppe Mazzini)
            2. Tach!

              Logisch können mehrere Linien einen oder mehrere gemeinsame Bahnhöfe haben, die kommen dann in der dritten Tabelle mehrfach vor.

              Mal sehen, wie lange es dauert, bis hier jemand nach Normalisierung ruft.

              Meinst du, dass eine m:n-Beziehung einer weiteren Normalisierung bedarf? Kann durchaus sein, dann aber eher für begleitende Daten, abseits der eigentlichen Beziehung, wenn diese mehrfach vorkämen.

              Problematisch wird es, wenn sich eine "Linie" auffächert, also in der einen Richtung andere Haltestellen anfährt als in der anderen Richtung.

              Dann kann man modelierungsmäßig zwei Linien (mit nur einer Richtung) draus machen oder man hat noch ein Flag, dass ein Überspringen bei Hin- oder Rückrichtung angibt.

              dedlfix.

              1. Hallo

                Logisch können mehrere Linien einen oder mehrere gemeinsame Bahnhöfe haben, die kommen dann in der dritten Tabelle mehrfach vor.

                Mal sehen, wie lange es dauert, bis hier jemand nach Normalisierung ruft.

                Meinst du, dass eine m:n-Beziehung einer weiteren Normalisierung bedarf?

                Nö, da hab' ich mich verhauen. Dies wohl, weil Linuchs in einem anderen Posting von nicht normalisierten Stationslisten schrieb, was ich auch „mit lfd. Stationsnummer innerhalb der Linie“ bezog. Aber auch, weil ich das etwas anders angehen würde und das Eine mit dem Anderen vermischt habe.

                Bei mir: Tabelle 1: Stationen, Tabelle 2: Linien, Tabelle 3: Stationen in Linien mit ihrer Reihenfolge. Schnittpunkte von Linien ergäben sich durch gleichlautende Stationseinträge in Tabelle 3.

                Problematisch wird es, wenn sich eine "Linie" auffächert, also in der einen Richtung andere Haltestellen anfährt als in der anderen Richtung.

                Dann kann man modelierungsmäßig zwei Linien (mit nur einer Richtung) draus machen oder man hat noch ein Flag, dass ein Überspringen bei Hin- oder Rückrichtung angibt.

                Ich würde Tor 1 nehmen. In Kursbüchern und auf den Abfahrt- und Ankunftsplänen von Bahnhöfen wird das ja grundsätzlich auch so gemacht, auch wenn dort jede Verbindung pro Zuglauf ihre eigene Nummer hat.

                Tschö, Auge

                --
                Es schimmerte ein Licht am Ende des Tunnels und es stammte von einem Flammenwerfer.
                Terry Pratchett, „Gevatter Tod“
                1. Tach!

                  Problematisch wird es, wenn sich eine "Linie" auffächert, also in der einen Richtung andere Haltestellen anfährt als in der anderen Richtung.

                  Dann kann man modelierungsmäßig zwei Linien (mit nur einer Richtung) draus machen oder man hat noch ein Flag, dass ein Überspringen bei Hin- oder Rückrichtung angibt.

                  Ich würde Tor 1 nehmen. In Kursbüchern und auf den Abfahrt- und Ankunftsplänen von Bahnhöfen wird das ja grundsätzlich auch so gemacht, auch wenn dort jede Verbindung pro Zuglauf ihre eigene Nummer hat.

                  Naja, eigentlich nur, wenn es ein kursbuchähnlicher Anwendungsfall ist. Da sind ja auch noch jede Menge anderer Daten (Züge und Uhrzeiten) unterzubringen. Wenn es lediglich eine Liniendarstellung wie beispielsweise in der Wikipedia bei den Bahnstrecken ist, dann plädiere ich eher für Tor 2.

                  dedlfix.

        3. PS: „Bahnlinie“ ist ein zusammengesetztes Substantiv.

          Ist mir bekannt. Ich neige jedoch dazu, meine Schreibe der Spreche anzupassen. Heute sah ich ein Schild hochkant in einem Abstellraum, da ging es um ein Messer.

          Ich musste dreimal lesen, bis ich es als Messe-restaurant erkannte.

          Linuchs

          1. Hallo

            PS: „Bahnlinie“ ist ein zusammengesetztes Substantiv.

            Ist mir bekannt. Ich neige jedoch dazu, meine Schreibe der Spreche anzupassen.

            Du sprichst das tatsächlich als zwei Worte aus? Ich nicht. Ich würd' nicht mal auf die Idee kommen.

            Heute sah ich ein Schild hochkant in einem Abstellraum, da ging es um ein Messer.

            Ich musste dreimal lesen, bis ich es als Messe-restaurant erkannte.

            Bei mir ist es der Brathering. Immer wieder …

            Tschö, Auge

            --
            Es schimmerte ein Licht am Ende des Tunnels und es stammte von einem Flammenwerfer.
            Terry Pratchett, „Gevatter Tod“
            1. Hallo,

              Ich musste dreimal lesen, bis ich es als Messe-restaurant erkannte.

              Dann aber bitte Messe-Restaurant.

              Bei mir ist es der Brathering. Immer wieder …

              Die Großschreibung macht's aber doch eindeutig?

              Gruß
              Kalk

              1. Hallo

                Bei mir ist es der Brathering. Immer wieder …

                Die Großschreibung macht's aber doch eindeutig?

                Auch wenn der vermutlich nur aural funktioniert, schreib' ich es hier rein.

                Wenn auf der Konservendose „Brathering“ steht und es wäre nicht Brathering sondern englischer brathering, würd dort dennoch „Brathering“ (mit großem B) draufstehn. Eigenname und so.

                Ist halt doof, wenn man selber den Gag mit dem englisch ausgesprochenen Brathering bringt und dann im Laden steht und sich fragt, was das wohl sein mag. Sowas von selbst reingelegt …

                Tschö, Auge

                --
                Es schimmerte ein Licht am Ende des Tunnels und es stammte von einem Flammenwerfer.
                Terry Pratchett, „Gevatter Tod“
                1. Hallo Auge,

                  Ist halt doof, wenn man selber den Gag mit dem englisch ausgesprochenen Brathering bringt und dann im Laden steht und sich fragt, was das wohl sein mag. Sowas von selbst reingelegt …

                  Nobody makes me my farmers early piece after.

                  Bis demnächst
                  Matthias

                  --
                  Das Geheimnis des Könnens liegt im Wollen. (Giuseppe Mazzini)
              2. Dann aber bitte Messe-Restaurant.

                Das habe ich mich auch gefragt, und mich dann bewusst für eine Trennung entschieden, wie sie am Zeilen-

                ende aussieht.

                Und ich dachte, nur GOtt steht zwei Großbuchstaben zu.

                Linuchs

                1. Hallo,

                  Dann aber bitte Messe-Restaurant.

                  Das habe ich mich auch gefragt, und mich dann bewusst für eine Trennung entschieden, wie sie am Zeilen-

                  ende aussieht.

                  Das sind aber zwei verschiedene Sachen. Silbentrennung am Ende einer Zeile führt natürlich nicht zur Großschreibung in der neuen Zeile. Die Trennung von einzelnen Bestandteilen eines zusammengesetzten Wortes mit Bindestrich zur besseren Lesbarkeit hat damit nichts zu tun.

                  Und ich dachte, nur GOtt steht zwei Großbuchstaben zu.

                  Na dann schau dir doch mal beispielsweise @Matthias Appels an, der hat auch zwei Großbuchstaben.

                  Gruß
                  Kalk

                2. Das habe ich mich auch gefragt, und mich dann bewusst für eine Trennung entschieden, wie sie am Zeilen-

                  ende aussieht.

                  Es geht ja nicht um Recht'schreibung, sondern um ein leichteres Lesen. Gerne nehme ich auch ein Zeichen, dass beim Singen dem Atem'zeichen entspricht.

                  Das Atemzeichen dient in der Notenschrift zur Kennzeichnung von Stellen, an denen der Sänger oder der Spieler eines Blasinstrumentes atmen kann.

                  Das ' zum Atmen beim Lesen ist aber merk'würdig, da würde eher ein Gedanken--strich passen. Aber woher nehmen auf der Tastatur?

                  Da gibt es tatsächlich Gedanken zum Strich bei Wikipedia

                  Vielleicht könnte der Halbgeviertstrich – Linux: [Alt Gr][-], der Viertelgeviertstrich oder gar der Geviertstrich oder Doppelgeviertstrich mein Kandidat sein.

                  Wenn es wie hier um Bahnstrecken geht, käme auch der Streckenstrich infrage

                  Streckenstrich[Bearbeiten]
                  
                  Der Halbgeviertstrich wird auch bei Streckenangaben eingesetzt.
                  
                  Dabei gibt es unterschiedliche Empfehlungen dazu, ob der Halbgeviertstrich durch Leerzeichen bzw. Spatia eingerahmt wird oder nicht.
                  
                  Für den Bürobereich empfehlen DIN 5008 und Ö-NORM A 1080 Leerzeichen um den Streckenstrich (z. B. „Wien – Krakau“).
                  

                  ... und natürlich der Bahnhofs-strich. Aber nicht der Brotauf-strich.

                  Linuchs

  3. Moin,

    #ON          trp1.id IN ( lin1.treffpunkt_ids )
    

    ...
    Die hier mit # ausgeblendete Version bringt nur einen Treffer, obwohl zwei Einträge im Feld lin1.treffpunkt_ids vorhanden sind.

    den einen Treffer bekommst du nur durch den LEFT JOIN, wobei dann die trp1 Felder NULL sind, weil keine entsprechende Beziehung vorhanden ist. Ein IN bedeuted nicht, dass in String gesucht wird.

    Die dann zwecks Test eingesetzten Treffpunkte bringen zwar zwei Treffer, aber nicht in der richtigen Reihenfolge.

    Es gibt auch keine Reihenfolge. Du müsstest die Ergebnisse nachfolgend sortieren, wenn du eine Sortierung haben möchtest. Aber auch diese nachfolgende Sortierung ist nichtig, wenn das Programm, wo die Daten nutzt, diese Reihenfolge ignoriert. Das kann zum Beispiel auch ganz ungewollt durch eine Parallelisierung erfolgen.

    hth bernd