Ankündigung

Einklappen
Keine Ankündigung bisher.

PostgreSQL: Join klappt nicht.

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • #31
    Zitat von protestix Beitrag anzeigen
    Du musst ihm beweisen das es falsch ist. so läuft das hier im Forum. Ansonsten könnte man - immer - jede Aussage anzweifeln, weil kein Beweis vorliegt im mathematischen Sinne.
    Ich muß nur sterben. Wenn es richtig ist, warum postet er nicht sein Ergebnis. Über alle 4 Trainingstermine ist das eine Abfrage mit 12 Datensätzen, so wie meine aus #10. Die kann jeder nachstellen, daher ist es unnötig, die jetzt hier zu posten. Seine kann ich nicht nachstellen, also posten. So einfach.

    Kommentar


    • #32
      Alf2016
      Was ist an meiner Lösung unsauber?

      @beweise
      Dass man in einem Forum beweisen muss, dass eine richtige oder bessere Lösung vorliegt, wäre mir neu. Sinnvoll wäre immerhin, dass sie nachvollziehbar ist. Das ist aber Ermessenssachem, erst Recht wenn es um "besser" geht. Vor allem wäre spannend, ob es für den TE interessant ist, wenn er bspw. zufällig sowieso gerade sein Datenmodell neu macht.
      Also ist es im Zweifel Spielerei oder eine Frage von Rechthaberei oder wer hat den längeren.

      Kommentar


      • #33
        Wenn ich schreibe, dass das Ergebnis stimmt, dann ist das auch so. Evtl. verwirrt das rowid, ich gebe immer dem ersten Feld jeder Tabelle die Bezeichnung rowid. Der Hinweis auf die 2 INNER JOINS und WHERE ist richtig, allerdings arbeite ich schon lange genug mit SQLite, dass ich genau weiß wann ein subselect einem inner join vorzuziehen ist. Hierüber will ich aber auch nicht diskutieren, weil es in den Bereich der Mikrooptimierung fällt.

        Das äußere select "select playername from" kann man auch weglassen, dass habe ich nur zur Veranschaulichung der except Geschichte geschrieben.

        es würde auch folgendes reichen:

        Anwesend:
        Code:
        select playername from
        (select player_id,(select rowid from trainings where datum = '2019-01-01') as trainID
        from teilnahme where training_id = trainID)
        inner join player on player.rowid = player_id
        Abwesend:
        Code:
        select playername from player
        except
        select playername from
        (select player_id,(select rowid from trainings where datum = '2019-01-01') as trainID
        from teilnahme where training_id = trainID)
        inner join player on player.rowid = player_id
        Wenn einer diese simplen Zeilen nicht nachvollziehen kann, so ist das nicht mein Problem. Es ging auch hauptsächlich darum, auf den Cross Join zu verzichten und zu zeigen, dass es im Grunde genügt, die anwesenden "Player" von allen "Player" abzuziehen.

        Kommentar


        • #34
          Offenbar haben sich oberste Stellen darauf geeinigt, daß subselects statt joins und
          Code:
          SELECT *
          jetzt doch kein Verstoß gegen Codierungs-Gepflogenheiten darstellt. So oder so: In jedem Falle lernt man hier immer dazu...

          Kommentar


          • #35
            Sarkastisches Augenrollen sollte man sich sparen, wenn man nicht 100% im Thema ist. Der Sinn eines subselects ist die Rückgabe eines einzelnen Wertes. Joins werden benutzt um rows zurückzugeben.

            Kommentar


            • #36
              Zitat von Alf2016 Beitrag anzeigen
              Offenbar haben sich oberste Stellen darauf geeinigt, daß subselects statt joins und
              Code:
              SELECT *
              jetzt doch kein Verstoß gegen Codierungs-Gepflogenheiten darstellt. So oder so: In jedem Falle lernt man hier immer dazu...
              Falls das eine Antwort auf meine Frage an Dich war, Alf2016:

              Ja, dazu ist ein Forum da, um dazu zu lernen. Das kann man einfach so nutzen, ohne dass Grabenkämpfe zu Rangordnungen oder was auch immer ausgeführt werden müssen.
              Ich habe in meinem Beitrag begründet, warum ich den Stern verwendet habe. Subselects habe ich nicht verwendet, sie sind oft ungünstig, bzw. produzieren ungünstiges Ausführungsverhalten, verstoßen aber allgemein nicht gegen irgendwelche mir bekannten Codierungsgepflogenheiten.

              Und auch wenn Du es anders siehst, ich habe keine Beweise nötig, ich schreibe nicht Dir, sondern dem TE. Wenn er meinen Vorschlag ausprobiert und gut findet ok, wenn er ihn nicht versteht oder doof findet, auch ok. Die meisten sind ja des Schreibens mächtig und können sich dann entsprechend äußern, wenn sie möchten.

              Damit bin ich zu gar nichts verpflichtet, außer die Forenregeln einzuhalten.
              Vielleicht kannst Du mir noch schreiben, wie Du dazu kommst, von "die oberen" zu schreiben.

              Kommentar


              • #37
                Zitat von Perry Staltic Beitrag anzeigen
                ...
                Vielleicht kannst Du mir noch schreiben, wie Du dazu kommst, von "die oberen" zu schreiben.
                Aber das Stilmittel der Ironie ist dir doch bekannt? Ich werde einen Teufel tun, da deutlicher zu werden. Ich habe hier einmal den Kollegen erc positiv hervorgehoben, in letzter Zeit sind auch die Beiträge von protestix recht vernünftig (natürlich gilt das immer nur, wo ich mit ihm zu tun habe). Alle anderen mögen daraus Schlußfolgerungen ziehen oder nicht.

                Kommentar


                • #38
                  Zitat von Alf2016 Beitrag anzeigen
                  Aber das Stilmittel der Ironie ist dir doch bekannt? ..
                  Ja natürlich, ich kann nicht nur SQL ich kann auch Ironie.
                  Ich sehe in Deinem Beitrag leider keine Antworten zu meinen Punkten. Und ich weiß auch sonst nicht, was Deine Worte aus #37 mir und anderen sagen sollen. Teilweise kann ich immerhin zustimmen, die genannten Mitglieder liefern gute Beiträge. Und erlaube mir, es Dir gleich zu tun: Manche von den Beiträgen, die ich von Dir gelesen hab sind auch ok. Ansonsten verbreitest Du leider auch viel Stunk und sagen wir mal heiße Luft. Das kannte ich so im Forum bis jetzt nicht.

                  Vielleicht kannst Du ja etwas damit anfangen, dass sich solche Foren auch Community nennen. Hier geht es tatsächlich um gemeinschaftliches Lernen, nichts anderes.

                  Kommentar


                  • #39
                    Zitat von kaminbausatz Beitrag anzeigen
                    @erc

                    Riesenwind und keine Lösung...
                    Du kannst das von mir aus Angriff sehen, du kannst das als produktive Kritik sehen, oder du kannst dich auch geehrt fühlen das ich auf dein Post eingegangen bin. Das mag großkotzig klingen, aber es hat sich jemand die Arbeit gemacht dein Beitrag zu lesen, zu verstehen und eine Antwort zu verfassen. Mir ist auch klar das dir eine Antwort alá "Die Idee mit dem EXCEPT find ich nett." lieber gewesen wäre. Perry Staltic hat es passenden ausgedrückt "gemeinschaftliches Lernen". Welcher Antwort hat den tendentiell das größere Potential? Was du draus machst ist letztendlich deine Entscheidung.

                    Was zum nachdenken für dich:

                    Zitat von kaminbausatz Beitrag anzeigen
                    Wenn ich schreibe, dass das Ergebnis stimmt, dann ist das auch so.
                    Sicher doch. Füg ein weiteres Training für ein bereits vorhandeenes Datum ein. SQL Fehler sind ein gutes Zeichen, dass mit dem Query was nicht stimmt. Du kannst mir jetzt natürlich erzählen das die Spalte unquie ist, aber spar es dir!

                    Zitat von kaminbausatz Beitrag anzeigen
                    allerdings arbeite ich schon lange genug mit SQLite, dass ich genau weiß wann ein subselect einem inner join vorzuziehen ist. Hierüber will ich aber auch nicht diskutieren, weil es in den Bereich der Mikrooptimierung fällt.
                    A. Die Abfrage in dem Subquery hat die höchste Selektivität (und auch einzige), als JOIN würde diese Tabelle zwangsläufig im Ausführungsplan den Anfang bilden. Verständlich warum du hier nicht über "Mikrooptimierung" "disktuieren" willst.

                    B. Wie bereits angedeutet ist dieser Subquery auch falsch platziert. Die (gedankliche) Rangfolge der SQL Klauseln ist FROM -> WHERE -> SELECT -> HAVING -> GROUP BY -> ORDER BY. Dein WHERE bezieht sich auf ein Ergebnis im SELECT, was aber das WHERE erst bildet. Das geht in Sqlite, ist aber unlogisch. Du verwendest diesen Wert dann auch nicht (hier fehlte dann die Lust auf Mikrooptimierung?) und durch die Positionierung im SELECT unterliegt das Ergebnis des Subqueries einschränkungen, siehe oben und weiter unten. Im WHERE könntest du das mit =,in,any,all sinnvoll Formulieren.

                    Zitat von kaminbausatz Beitrag anzeigen
                    Wenn einer diese simplen Zeilen nicht nachvollziehen kann, so ist das nicht mein Problem.
                    Ja klar, die anderen sind immer das Problem. Manchmal auch einfach mal an die eigenen Nasse fassen. Und so simple wars dann scheinbar auch nicht, oder wo kommt der SQL Fehler her?

                    Zitat von kaminbausatz Beitrag anzeigen
                    Es ging auch hauptsächlich darum, auf den Cross Join zu verzichten[...]
                    Indem du das Problem geändert hast. Du betrachtest nur "ein" Training.

                    Zitat von kaminbausatz Beitrag anzeigen
                    Sarkastisches Augenrollen sollte man sich sparen, wenn man nicht 100% im Thema ist. Der Sinn eines subselects ist die Rückgabe eines einzelnen Wertes. Joins werden benutzt um rows zurückzugeben.
                    Wenn du "100% im Thema" erzählst, sollte der nächste Satz nicht gleich Bullshit sein. Das Ergebnis eines Subqueries ist aus Entwicklersicht eine (dynamische) Tabelle oder View. Im SELECT unterliegt das Ergebnis der Einschränkung max 1 Datensatz mit einer Spalte. Im WHERE im FROM gibts keine Einschränkungen. Das Ergebnis eines Subqueries kann auch gejoint werden.

                    Kommentar


                    • #40
                      Zitat von Perry Staltic Beitrag anzeigen
                      Ja natürlich, ich kann nicht nur SQL ich kann auch Ironie.
                      Ich sehe in Deinem Beitrag leider keine Antworten zu meinen Punkten. Und ich weiß auch sonst nicht, was Deine Worte aus #37 mir und anderen sagen sollen. Teilweise kann ich immerhin zustimmen, die genannten Mitglieder liefern gute Beiträge. Und erlaube mir, es Dir gleich zu tun: Manche von den Beiträgen, die ich von Dir gelesen hab sind auch ok. Ansonsten verbreitest Du leider auch viel Stunk und sagen wir mal heiße Luft. Das kannte ich so im Forum bis jetzt nicht.

                      Vielleicht kannst Du ja etwas damit anfangen, dass sich solche Foren auch Community nennen. Hier geht es tatsächlich um gemeinschaftliches Lernen, nichts anderes.
                      Meine Kritik bezog sich in erster Linie auf kaminbausatz. Du ziehst dir da tw. Schuhe an, die gar nicht für dich bestimmt sind.

                      erc Du hast eine pn.

                      Kommentar


                      • #41
                        erc

                        Ich verzichte mit Bedacht darauf, deine Ausführungen zu zitieren, das ermöglicht dir die reichlich vorhandenen Rechtschreibfehler zu korrigieren. Ich hoffe ja, dass du nicht ebenso programmierst.

                        Diese Spitze musste einfach sein, sorry.

                        Im Einzelnen:

                        „füge ein weiteres Training für ein vorhandenes Datum ein“, müsste da nicht auch die Tabelle trainings ein weiteres Unterscheidungsmerkmal aufweisen?

                        Die Struktur wurde vorgegeben.

                        Über die Subquery will ich nicht diskutieren, solange du mir kein schnelleres Beispiel zeigst. Eine Suche nach 'join vs. subquery' liefert sehr viele unterschiedliche Ergebnisse. Das scheint ein Fall für die Kirche zu sein.

                        Das Problem habe ich nicht geändert, der TE wollte wissen, wer an an welchem Tag nicht beim Training war. Das erklärt auch deine letzte Anmerkung. Ich wollte beabsichtigt nur den einen Datensatz.

                        Ich weiß nicht, von welchem SQL Fehler du redest, habe leider die Daten nicht mehr auf dem Handy. Werde sie allerdings auch nicht mehr neu eingeben, weil es sicher und zuverlässig funktioniert. Ich habe das getestet.

                        Die Diskussion entstand ja nur, weil ich in #11 bereits andeutete, dass ich bei Cross-Joins immer vorsichtig bin, wenn ich das Datenvolumen nicht kenne.

                        Ich bediene mich jetzt mal aus deinem Wortschatz. Es ist „Bullshit“ einen riesigen Cross-Join zu erzeugen, wenn ich auf dem Bildschirm nur max. 30 Zeilen mit 8 Spalten oder auf dem einzelnen DIN A4 Ausdruck nur max. 80 Zeilen mit 7 Spalten betrachten kann.

                        Wenn ein Cross-Join eingesetzt wird, dann nur mit vorhersehbarem definiertem Umfang, sonst kann man dies als "groben Unfug" bezeichnen.

                        Ist eine Liste gewünscht, würde ich das Problem in SQLite eher wie folgt anpacken. Ich schreibe SQLite, weil ich es diesmal nicht getestet habe, aber sicher bin, dass es so in SQLite funktioniert.

                        Code:
                        SELECT datum, player.playername, count(*)%2 as anwesend
                        FROM   trainings
                               JOIN teilnahme ON teilnahme.training_id != trainings.trainings_id
                               JOIN player ON player.player_id = teilnahme.player_id
                        where datum >= '2019-01-01' and datum < '2019-10-10'
                        Group by datum, playername
                        "where" damit es größenmäßig nicht ausufert. Die 2 joins erzeugen eine größere Ergebnismenge als ein Cross-Join. Das ist beabsichtigt.

                        Kommentar


                        • #42
                          Zitat von kaminbausatz Beitrag anzeigen
                          erc

                          Ist eine Liste gewünscht, würde ich das Problem in SQLite eher wie folgt anpacken. Ich schreibe SQLite, weil ich es diesmal nicht getestet habe, aber sicher bin, dass es so in SQLite funktioniert.

                          Code:
                          SELECT datum, player.playername, count(*)%2 as anwesend
                          FROM trainings
                          JOIN teilnahme ON teilnahme.training_id != trainings.trainings_id
                          JOIN player ON player.player_id = teilnahme.player_id
                          where datum &gt;= '2019-01-01' and datum &lt; '2019-10-10'
                          Group by datum, playername
                          Macht nicht das, was der TE bereits in seinem allerersten Beitrag im betr. Thread schrieb. Aber bemühe dich nicht, es wurde ja bereits von Perry Staltic sowie von mir überzeugende Lösungen geboten.

                          Kommentar


                          • #43
                            Jetzt sind wir schon bei den Rechtschreibfehlern!

                            Zum Sachverhalt bei Cross Joins:
                            Vorsicht ist sicher nicht verkehrt, wobei es wie so oft mit den Fehlern ist, man macht es nicht absichtlich.

                            Ein Cross Join kann ohne weiteres mit einer Where Clause beschnitten werden und verhält sich entsprechend brav.
                            Code:
                            select *,
                                   case
                                   when training_id is null
                                   then 'nicht anwesend'
                                   else 'anwesend' end as generated_remark
                              from player p  cross join trainings t
                              left join player_training pt
                                     on (t.tid, p.pid) = (pt.training_id,pt.player_id)
                             where tdate between '2019-02-02'::date and  '2019-04-02'::date
                                   -- oder ...
                                   -- tdate < CURRENT_DATE - INTERVAL '45 day')::date -- älter als 45 Tage
                                   -- tid = 3                          -- genau 1 bestimmtes Training nach ID
                                   -- tid in (3,5,6)                   -- genau 3 bestimmte Trainings nach ID
                                   -- tdate =  '2019-02-02'::date      -- Trainings eines Tages
                             order by <ReplaceWithWhatEverYouNeed>
                            Wem das zu unsicher ist, weil ja mal die Abfrageparameter zu locker gesetzt werden können, der kann ein hartes Limit nach Anzahl auf eine der (sinnvoll auswählen) Quelltabellen setzten. Idealerweise harmoniert das mit Beschränkungen und Erläuterungen in der UI.

                            Und die Diskussion Subselect oder Join kann so gar nicht geführt werden. Man müsste das nicht nur DB spezifisch machen, sondern auch das Datenmodell, die Mengengerüste, die Werteverteilung und die Indizierung berücksichtigen.
                            M.E. macht es nicht viel Sinn, sich darüber zu streiten, ob man einen deterministischen Weg durch die Gehirnwindungen des Optimizer Developer Teams findet. Selbst mit festem Datenmodell machen die Daten selbst einem einen Strich durch die Rechnung.

                            Kommentar


                            • #44
                              Zitat von Perry Staltic Beitrag anzeigen
                              ...Ein Cross Join kann ohne weiteres mit einer Where Clause beschnitten werden und verhält sich entsprechend brav.
                              Weise Erkenntnis, die auch die von kaminbausatz vorgeschobene Performance-Debatte in einem Streich vom Tisch wischt, aber keinesfalls neu.
                              Code:
                              select *,
                              ...
                              where tdate between '2019-02-02'::date and '2019-04-02'::date
                              ...
                              order by <ReplaceWithWhatEverYouNeed>
                              Kommt meinem bereits in #10 geposteten Vorschlag gefährlich nahe - und erregt damit den Verdacht, richtig zu sein. Zur Erinnerung, das sah so aus:
                              Code:
                              SELECT A.trainingsdatum, IF(ISNULL(training_id), "fehlt", "teilgen.") AS Teilnahme,
                                        A.name
                                  FROM   player_training
                                        RIGHT JOIN
                                                   (SELECT player.id AS pid, player.name, trainings.id AS tid,
                                                           trainings.trainingsdatum
                                                           FROM player, trainings) as A
                                        ON player_training.player_id = A.pid
                                        AND player_training.training_id = A.tid
                                  ORDER BY A.trainingsdatum, Teilnahme DESC, A.name;
                              Wenn Perry Staltic jetzt auch noch das SELECT * entfernen würde und im ORDER BY was sinnvolles und eben nicht "was immer..." stehen würde, wäre es für den ursprünglichen Zweck, eine Liste für die Auswertung in größeren Zeitabständen zu erstellen, tatsächlich schon fast geeignet... Aber eben nur fast, denn um aus dem Abfrageergebnis nach dem obigen Muster eine "hübsche Liste" á la AKretschmer (#5) zu machen wäre eine Schleife mit Gruppenwechsel angeraten und da ist "sortiert schon nicht schlecht". Die gleiche Notwendigkeit würde sich bei einer selbstgebauten Aggregations-Funktion & GROUP BY, nur etwas anders stellen, wobei dort sicher das "*" ein No-go wäre.

                              Oder eben wie AKretschmer PostgreSQL verwenden, es aber richtig bedienen können (bzw. die Fehler, die es macht, erkennen können, denn das Ergebnis war ja nun wirklich ganz offensichtlich fehlerhaft...). Aber auch da kann ich mir vorstellen, daß eine saubere Feldliste statt "*" und eine sinnvolle Sortierung hilfreich sein könnte...

                              Zur Performance-Debatte, die Perry Staltic ja dankenswerterweise eigentlich schon vom Tisch gefegt hatte:
                              ...
                              M.E. macht es nicht viel Sinn, sich darüber zu streiten, ob man einen deterministischen Weg durch die Gehirnwindungen des Optimizer Developer Teams findet. Selbst mit festem Datenmodell machen die Daten selbst einem einen Strich durch die Rechnung.
                              Diese Debatte war eigentlich längst allein dadurch vom Tisch, daß der TE in seinem Modell bereits zum Eintrag aller Trainingstermin/Spieler-Kombinationen in seiner n:m-Tabelle übergegangen war.

                              Aber das hat man über die Theorie-Debatte und im Eifer des Gefechts - oh, sorry: über "das gemeinschaftliche Lernen" - glatt vergessen...

                              Ich denke, diesen Thread kann man nun wirklich auch schließen. Aber bitte, wenn jemand noch ein Wort zum Samstag anschließen möchte, ich will mich da nicht vordrängen... Für mich ist alles gesagt.

                              Kommentar


                              • #45
                                Zitat von Alf2016 Beitrag anzeigen
                                Oder eben wie AKretschmer PostgreSQL verwenden,
                                Aha.
                                Überschrift des Threads:
                                PostgreSQL: Join klappt nicht.

                                LG jspit


                                PHP-Klassen auf github

                                Kommentar

                                Lädt...
                                X