Herbi: 2 SQL Abfragen kombinieren

Hallo zusammen,

ich möchte gerne zwei SQL Abfragen miteinander "kombinieren". Ehe ich lange in der Theorie erkläre, schildere ich lieber das konkrete Beispiel. Ich habe  eine Datenbank mit diversen Einträgen. Es sollen zunächst einmal die 5 neuesten Einträge herausgesucht werden:

SELECT * FROM tabelle ORDER BY datum DESC LIMIT 5

Dann möchte ich, dass alle Einträge, die in der Spalte "option" ein "ja" zu stehen haben, angezeigt werden.

SELECT * FROM tabelle WHERE option='ja' ORDER BY datum DESC

Soweit ist alles klar. Ich möchte es nun aber hinkriegen, dass sowohl die 5 neuesten Einträge (s. Abfrage 1), als auch *alle* Einträge mit option = ja ausgegeben werden, und zwar innerhalb einer SQL-Abfrage.

Kann mir jemand helfen, wie ich dafür vorzugehen habe?

Vielen dank im Vorraus,
Herbi

  1. Hallo,

    welches Datenbankmanagementsystem in welcher Version verwendest Du?

    Es sollen zunächst einmal die 5 neuesten Einträge herausgesucht werden:
    SELECT * FROM tabelle ORDER BY datum DESC LIMIT 5

    Ich vermute MySQL.

    Dann möchte ich, dass alle Einträge, die in der Spalte "option" ein "ja" zu stehen haben, angezeigt werden.
    SELECT * FROM tabelle WHERE option='ja' ORDER BY datum DESC

    Ich möchte es nun aber hinkriegen, dass sowohl die 5 neuesten Einträge (s. Abfrage 1), als auch *alle* Einträge mit option = ja ausgegeben werden, und zwar innerhalb einer SQL-Abfrage.

    UNION sollte Dir helfen. Beachte die Hinweise, wie Du ein Teilergebnis limitierst und wie das Gesamtergebnis sortiert wird.

    Was ist mit den Einträgen unter den neuesten Einträgen, die in der Spalte 'option' den Wert 'ja' haben?

    Freundliche Grüße

    Vinzenz

    1. Hallo Vinzenz,

      welches Datenbankmanagementsystem in welcher Version verwendest Du?
      Ich vermute MySQL.

      Richtig. MySQL-Client-Version: 4.1.13

      UNION sollte Dir helfen. Beachte die Hinweise, wie Du ein Teilergebnis limitierst und wie das Gesamtergebnis sortiert wird.

      Das scheint der richtige Weg zu sein. Ich bekomme mit UNION alle Befehle ausgegeben. Es hapert nur an der richtigen Sortierung. Auf der verlinkten Seite steht, man müsse das so machen:

      (SQL Abfrage 1) UNION (SQL Abfrage 2) ORDER BY xyz

      Das habe ich mal so versucht, aber sobald ich das ORDER BY hinter die 2. SQL Abfrage nach der schließenden Klammer setze, erhalte ich null Ergebnisse. Packe ich das ORDER BY in die Klammern klappt alles, aber natürlich sind dadurch beide Abfragen nur jeweils für sich sortiert.

      So siehts derzeit bei mir aus

      (SELECT * FROM tabelle1, tabelle2 WHERE tabelle1.status='on' && tabelle1.gueltig > ".$cfg['time']." && tabelle1.id = tabelle2.id &&  tabelle1.option= 'ja')  
        
      UNION  
        
      (SELECT * FROM tabelle1, tabelle2 WHERE tabelle1.status='on' && tabelle1.gueltig > ".$cfg['time']." && tabelle1.id = tabelle2.id ORDER BY tabelle1.datum DESC LIMIT 5)  
        
      ORDER BY tabelle1.datum DESC
      
      1. Ok ich glaube es liegt daran:

        "This kind of ORDER BY cannot use column references that include a table name (that is, names in tbl_name.col_name  format). Instead, provide a column alias in the first SELECT statement and refer to the alias in the ORDER BY. (Alternatively, refer to the column in the ORDER BY using its column position. However, use of column positions is deprecated.)"

        Allerdings versteh ich nicht so recht was mit der Aussage "provide a column alias in the first SELECT statement and refer to the alias in the ORDER BY" gemeint ist. Kann mir das vielleicht jemand anhand meines Beispiels (einen Beitrag höher) erläutern?

        Ich hab zwar hier SQL Alias rausgefunden, wie es theoretisch gehen müsste, aber meine Versuche das zu übertragen haben nicht funktioniert... :-(

        Vielen Dank im Vorraus,
        Herbi

        1. Hello,

          das Handbuch sollte dir da eigentlich direkt zeigen, wie es falsch und richtig aussieht:
          ---
           Ferner muss, wenn einer zu sortierenden Spalte ein Alias zugewiesen wird, die ORDER BY-Klausel den Alias und nicht den Spaltennamen referenzieren. Die erste der folgenden Anweisungen funktioniert – im Gegensatz zur zweiten, die mit dem Fehler Unknown column 'a' in 'order clause'  fehlschlägt:
          ---

          Falsch:
          (SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY a;
          du kannst nicht nach "a" sortieren, da es außerhalb des UNION nicht mehr adressiert werden kann

          Richtig:
          (SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY b;
          Du vergibst für die Spalte a einen Aliasnamen "b", nach dem du nun sortieren kannst.
          Ich vermute zudem, auch wenn nicht explizit genannt und von der Nachvollziehbarkeit her ein Alptraum, dass du auch den Index der Sortierspalte angeben kannst, also etwa ORDER BY 1

          MfG
          Rouven

          --
          -------------------
          sh:| fo:} ch:? rl:( br:& n4:{ ie:| mo:} va:) js:| de:] zu:| fl:( ss:) ls:& (SelfCode)
          "I wish it need not have happened in my time" - "So do I, and so do all who live to see such times. But that is not for them to decide. All we have to decide is what to do with the time that is given us."  --  J.R.R. Tolkien: "The Lord Of The Rings: The Fellowship Of The Ring"
          1. Hallo Rouven,

            danke für Deine Mühen. Soweit hatte ich es auch verstanden. ORDER BY tabelle1.datum funktioniert nicht, weil ich tabelle1.datum erst ein column alias zuweisen muss.

            Mein Problem lautet: Wie weise ich in diesem Beispiel:

            (SELECT * FROM tabelle1, tabelle2 WHERE tabelle1.status='on' && tabelle1.gueltig > ".$cfg['time']." && tabelle1.id = tabelle2.id && tabelle1.option= 'ja')

            tabelle1.datum ein column alias, z.B. "datum" zu?

            1. Hello,

              (SELECT * FROM tabelle1, tabelle2 WHERE tabelle1.status='on' && tabelle1.gueltig > ".$cfg['time']." && tabelle1.id = tabelle2.id && tabelle1.option= 'ja')

              oha, nun ja.
              1.
              Ich halte es ja schon für unklug, bei einer einzelnen Tabelle SELECT * zu schreiben, aber bei einem JOIN mit SELECT * zu arbeiten verdoppelt ja gleich die Wahrscheinlichkeit, unerwartete Spalten zu kriegen. Wir haben die Diskussion hier öfter, ob SELECT * jetzt schlimm ist oder nicht. Im Fall von UNION kommt dem eine gewisse Brisanz zu denn das UNION ist darauf angewiesen, dass alle Abfragen exakt die gleichen Spalten in exakt der gleichen Reihenfolge liefern.
              Wenn du die Spalten also explizit auflistest, verringerst du das Risiko von Problemen und bringst dich gleichzeitig deinem Alias näher:

                
              SELECT tabelle1.spalte1, tabelle1.spalte2, tabelle2.spalte1, tabelle2.spalte2... FROM tabelle1, tabelle2 WHERE tabelle1.status='on' && tabelle1.gueltig > ".$cfg['time']." && tabelle1.id = tabelle2.id &&  tabelle1.option= 'ja'  
              
              

              2.
              Die Syntax "tabelle1, tabelle2" halte ich darüberhinaus auch für unglücklich. Wenn du mehr wissen willst, dann lege ich dir z.B. meinen Artikel zu JOINs und Vinzenz Fortsetzung Fortgeschrittene Joins ans Herz.

              MfG
              Rouven

              --
              -------------------
              sh:| fo:} ch:? rl:( br:& n4:{ ie:| mo:} va:) js:| de:] zu:| fl:( ss:) ls:& (SelfCode)
              He is entertaining both out of the car and in the car because if you tell him that a corner is almost flat then he is the guy who is going to try to take it flat even if it means shunting it the other side of it, he will come with the data and say 'hey, I may have crashed and destroyed the car, but I was flat-out'. That is an interesting quality that he has!  --  Team Member on Jacques Villeneuve
              1. Hallo Rouven,

                danke für Deine ausführliche Antwort. Ich habe das * jetzt entfernt und die Spalten einzeln aufgelistet, dabei hat auch das Zuweisen eines alias funktioniert und nun klappt es auch mit der richtigen Sortierung des UNION Befehls.

                Viele Grüße,
                Herbi

      2. Hello,

        Das habe ich mal so versucht, aber sobald ich das ORDER BY hinter die 2. SQL Abfrage nach der schließenden Klammer setze, erhalte ich null Ergebnisse.

        ähm, dann hast du einen Fehler in deinem PHP-Skript. Die Sortierung kann nur greifen oder nicht - du hast demnach einen von MySQL angekreideten Syntaxfehler ignoriert, kann das sein?

        MfG
        Rouven

        --
        -------------------
        sh:| fo:} ch:? rl:( br:& n4:{ ie:| mo:} va:) js:| de:] zu:| fl:( ss:) ls:& (SelfCode)
        Let Bygones Be Bygones  --  Robert Pitscottie: "Chronicles of Scotland"
        1. Hi Rouven,

          ähm, dann hast du einen Fehler in deinem PHP-Skript. Die Sortierung kann nur greifen oder nicht - du hast demnach einen von MySQL angekreideten Syntaxfehler ignoriert, kann das sein?

          Ich vermuete mal der Fehler liegt eher hier begründet:

          http://forum.de.selfhtml.org/?t=182699&m=1209227

          Gruß, Herbi

          1. Hello,

            Ich vermuete mal der Fehler liegt eher hier begründet:

            ja, siehe auch mein Kommentar da, aber nur weil du ein ORDER BY angibst, liefert eine Abfrage nicht nichts mehr zurück. Sie liefert die selbe Datensatzmenge wie vorher, nur halt anders sortiert, oder halt nicht, wie bei MySQL+UNION+ORDER BY ohne LIMIT. Wenn bei dir Ergebnisse nicht vorhanden sind, dann ist eher davon auszugehen, dass du den Fehler der Art "unknown column a in ..." ignoriert hast.

            MfG
            Rouven

            --
            -------------------
            sh:| fo:} ch:? rl:( br:& n4:{ ie:| mo:} va:) js:| de:] zu:| fl:( ss:) ls:& (SelfCode)
            Inter Arma Enim Silent Leges  --  Cicero