Bernd: zwei Abfragen in einer MySQL Abfrage?

Hallo,

ist es möglich in einer MYSQL Abfrage direkt zwei Abfragen zu tätigen? In meiner ersten hole ich alle Projekte die sich in der Datenbank befinden

$sql_Projekte = "SELECT p_titel, p_von, p_bis FROM projekte ";

$statement_Projekte = $mysqli->prepare($sql_Projekte);
$statement_Projekte->execute();

$result_Projekte = $statement_Projekte->get_result();

Jetzt habe ich noch eine zweite Tabelle mit dem Namen projektbilder. Wenn dort Bilder von einem Projekt hinterlegt sind, nur dann sollen die Projekte auch angezeigt mit dem Hinweis, es sind xxx Bilder vorhanden.

Ist dieses irgendwie möglich?

  1. Hallo Bernd,

    füge einen Subselect hinzu.

    SELECT p_titel, p_von, p_bis, (SUBSELECT) as anz_bilder
    FROM projekte 
    

    Verstehensenergiebooster: Finde einen Select, der Dir für ein Projekt die Anzahl der dafür vorhandenen Bilder bestimmt, und den Du für SUBSELECT einsetzen kannst.

    Rolf

    --
    sumpsi - posui - clusi
    1. Hallo,

      ich dachte er ich komme so weiter

      SELECT p_code, p_titel, p_von, p_bis (SELECT COUNT(*) FROM projektbilder WHERE bild_refID = p_code ) as anz_bilder FROM projekte
      

      aber da erhalte ich in phpMyAdmin eine Fehlermeldung

      #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT COUNT(*) FROM projektbilder WHERE bild_refID = p_code ) as anz_bilder FRO' at line 1

      1. Hallo Bernd,

        stimmt da hat Du was geschrieben das nicht der SQL Syntax entspricht auf sowas muss man wenn man keine Meldung haben will schon achten.

        Den gleichen Fehler, den Du in deinem Statement hast, habe ich in vorstehendem Satz gemacht. Mehrfach 😉

        Rolf

        --
        sumpsi - posui - clusi
        1. Jetzt habe ich es versucht

          SELECT * FROM projekte P
          WHERE NOT EXISTS (
              SELECT * FROM projektbilder PB
              WHERE EXISTS (
                  SELECT * FROM projekte P1
                  WHERE P1.p_code = PB.bild_refID
                  AND P1.p_code = P.p_code))
          

          Geht wohl auch nicht, ich kann mich nicht mehr in phpMyAdmin einloggen. Super. Ich mach es wohl doch lieber mit einem zweiten SQL.

          1. Ich habe es

            SELECT a.p_code, `p_id`, `p_titel`
            FROM projekte AS a
            LEFT JOIN projektbilder  AS b ON a.p_code = b.bild_refID
            WHERE b.bild_refID IS NOT NULL GROUP by p_id
            
            1. Hallo Bernd,

              okay, so bekommst Du alle Projekte, die Bilder haben. Die Anzahl fehlt.

              Aber warum jetzt ein neuer Ansatz? Du warst doch schon fast am Ziel. Es fehlte nur ein dummes, kleines Komma. Ich dachte, mein kommafreier Satz hätte Dich drauf gebracht.

              SELECT p_code, p_titel, p_von, p_bis (SELECT COUNT(*) FROM projektbilder WHERE bild_refID = p_code ) as anz_bilder FROM projekte

              Was inhaltlich noch fehlt, ist die Begrenzung auf Projekte mit Bildern.

              MYSQL erlaubt Dinge, die sonst nirgends gehen. Darum weiß ich nicht, ob man eine Subselect-Spalte in einer WHERE Bedingung verwenden darf. MS SQL Server erlaubt es nicht. Also dies hier:

              SELECT p_code, p_titel, p_von, p_bis,
                     (SELECT COUNT(*) FROM projektbilder 
                      WHERE bild_refID = p_code ) as anz_bilder 
              FROM projekte
              WHERE anzahl > 0
              

              Wenn MySQL das erlaubt, wäre es das, was Du brauchst. Denke ich.

              Wenn nicht - normgerechteres SQL sähe so aus:

              SELECT * 
              FROM (SELECT p_code, p_titel, p_von, p_bis,
                           (SELECT COUNT(*) FROM projektbilder 
                            WHERE bild_refID = p_code ) as anz_bilder 
                    FROM projekte) X
              WHERE anzahl > 0
              

              Alternativ mit einem Inner Join, das ist das gleiche wie ein LEFT JOIN bei dem man abfragt ob keine Sätze zugemischt wurden:

              SELECT p_code, p_titel, p_von, p_bis, COUNT(*)
              FROM projekte P JOIN projektbilder B ON B.bild_refID = P.p_code
              GROUP BY p_code, p_titel, p_von, p_bis
              

              In MYSQL reicht es, p_code ins GROUP BY zu schreiben, sofern es zu einem p_code nur einen Satz in der projekte-Tabelle gibt. Normgerechtere DBs verlangen, dass alle SELECT-Spalten, die nicht aggregiert werden, im GROUP BY gelistet sind und damit auch an der Gruppierung teilnehmen (was bei eindeutigem p_code zum gleichen Ergebnis führt).

              Rolf

              --
              sumpsi - posui - clusi
              1. Hallo,

                vielen Dank für deine Erklärung. Ich habe mich für diese Variante entschieden

                SELECT * 
                FROM (SELECT p_code, p_titel, p_von, p_bis,
                             (SELECT COUNT(*) FROM projektbilder 
                              WHERE bild_refID = p_code ) as anz_bilder 
                      FROM projekte) X
                WHERE anzahl > 0
                

                Allerdings bei WHERE nicht anzahl sondern anz_bilder ;)

                MYSQL erlaubt Dinge, die sonst nirgends gehen

                Was meinst du damit?

                Dann hätte ich noch eine Frage. Ist es möglich Bilder sortieren zu lassen? Erst alle 200x150 und danach mit ein wenig Abstand 200x267

                1. Hallo Bernd,

                  Bilder sortieren kannst Du nicht, aber die Datenbanksätze, die die Informationen zum Bild enthalten, kann man nach der Höhe des Bildes sortieren. Das kannst Du im SQL machen oder nachgelagert im PHP.

                  Das ist dann aber eine andere Query. In der bisher diskutierten Abfrage ging es um die Anzahl der Bilder pro Projekt.

                  Der kleine Abstand ist aber keine Frage des SQL, sondern des PHP. Wenn Du das HTML für die Bilder erzeugst, kannst Du abfragen ob sich von SQL-Row zu SQL-Row die Höhe ändert, und dann via HTML Abstand erzeugen (z.B. durch Hinzufügen einer class neue-höhe, die per CSS Regel einen größeren margin-top erzeugt). Alternativ könnte man die Bilder, die gleiche Höhe haben, auch in einen eigenen HTML Container einschließen (div, section, ul, je nach gewünschter Semantik) und durch das Styling des Containers den Extraabstand erzeugen. Wenn der Container eine flexbox mit row-wrap ist, könntest Du damit die Bilder auch in Zeilen anordnen und bei Höhenwechsel einen Umbruch produzieren. Das Spektrum der Möglichkeiten ist breit.

                  Rolf

                  --
                  sumpsi - posui - clusi
      2. Moin,

        Sag ihm doch bitte das einfach ein Komma fehlt(e). und ein Count(*) würde ich persönlich auch nie notieren.

        Gruß Bobby

        --
        -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <- ### Henry L. Mencken ### -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <- ### Viktor Frankl ### ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
        1. Hallo bobby,

          einen Kommafehler selbst zu finden ist deutlich lehrreicher. Ich habe Bernd hier schon so viel vorgekaut, da muss er auch selbst mal knabbern 😉. Nachdem er einen anderen Weg eingeschlagen hatte, habe ich ihm das mit dem Komma ja auch erzählt.

          Mal abgesehen von unterschiedlichen Vorstellungen zur Wissensvermittlung - was spricht gegen COUNT(*), um etwas zu zählen? Was ist dein persönlicher besserer Ansatz?

          Rolf

          --
          sumpsi - posui - clusi
          1. Moin,

            ok. Ich nehms zurück. Ich hätte ein indiziertes Feld genommen, was aber durch dne Abfragetyp "SIMPLE" keinen Unterschied macht.

            Sorry

            Gruß Bobby

            --
            -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <- ### Henry L. Mencken ### -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <- ### Viktor Frankl ### ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
            1. Hallo bobby,

              natürlich hast Du recht mit dem Hinweis, dass man in einem Subselect wie diesem

              SELECT COUNT(*) FROM projektbilder WHERE bild_refID = p_code

              darauf achten muss, dass die im WHERE verwendete Spalte (bild_refID) indexiert ist. Andernfalls hat man einen Subselect mit Tablescan und der Festplattenhersteller freut sich.

              Rolf

              --
              sumpsi - posui - clusi