berlinsurfer: Subqueryfrage

Liebe selfhtml-Gemeinde,
ich habe ein Problem mit einem SQL-Query (ich merke gerade, dass viele Fragen mit "Ich habe eine Problem ..." anfangen, sei's drum).
Folgender Query funktioniert wunderbar:
$sql = "SELECT *,
      (SELECT IntPrintDate FROM #__vdm_teil2 teil2 WHERE db.IntTeil2ID = teil2.ID) as zlb_datum,
      (SELECT NumZLB FROM #__vdm_teil2 teil2 WHERE db.IntTeil2ID = teil2.ID) as zlb_nr
      FROM #__vdm_db db WHERE IntFzgFlotteID = $fzgid AND IntStatus = 'G'";

Meine Frage: kann ich beide Werte (zlb_nr + zlb_datum) mit einem Subquery erschlagen ? Wenn ich beide in einen Query packe, kommt "Operand should contain 1 column(s)", gibt es dort eine Möglichkeit ?
Danke schon mal & Gruß aus Berlin,
Jan

  1. Hi,

    Meine Frage: kann ich beide Werte (zlb_nr + zlb_datum) mit einem Subquery erschlagen ?

    nein, aber mit einem Join.

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:| br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
    1. Hallo Cheatah,
      danke für deine Antwort.
      Du meinst so:
          $sql = "SELECT
            (SELECT ID FROM #__vdm_fzgflotte WHERE FIN = '$fin' AND IntStatus = 'G') as fzgid,
            db.*, teil2.IntPrintDate as zlb_datum, teil2.NumZLB as zlb_nr
            FROM #__vdm_db db, #__vdm_teil2 teil2
            WHERE db.IntTeil2ID = teil2.ID
            HAVING db.IntFzgFlotteID = fzgid AND db.IntStatus = 'G'";

      Als implizites Inner Join ? Das funktioniert auch super, danke. Ist das denn viel schneller ?
      Danke & Gruß,
      Jan

      1. Mahlzeit berlinsurfer,

        Ich würde eher meinen so:

        SELECT (SELECT ID FROM #__vdm_fzgflotte WHERE FIN = '$fin' AND IntStatus = 'G') AS fzgid  
        ,      db.*  
        ,      teil2.IntPrintDate AS zlb_datum  
        ,      teil2.NumZLB AS zlb_nr  
          FROM #__vdm_db    db  
          JOIN #__vdm_teil2 teil2 ON db.IntTeil2ID = teil2.ID  
         WHERE db.IntFzgFlotteID = fzgid AND db.IntStatus = 'G'
        

        Als expliziten JOIN. Die sind IMHO erheblich besser lesbar.

        Ist das denn viel schneller ?

        Befrage dazu Deine Datenbank.

        MfG,
        EKKi

        --
        sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
        1. Danke EKKi,
          das letzte WHERE habe ich durch ein HAVING ersetzt (ansonsten hat er gemerkt 'Unknown column fzgid'), so dass es jetzt so aussieht:

          "SELECT  
                (SELECT ID FROM #__vdm_fzgflotte WHERE FIN = '$fin' AND IntStatus = 'G') AS fzgid,  
                db.*,  
                teil2.IntPrintDate AS zlb_datum,  
                teil2.NumZLB AS zlb_nr  
                FROM #__vdm_db db  
                JOIN #__vdm_teil2 teil2 ON db.IntTeil2ID = teil2.ID  
                HAVING db.IntFzgFlotteID = fzgid AND db.IntStatus = 'G'";  
          
          

          Danke euch beiden.
          Gruß,
          Jan

          1. Mahlzeit berlinsurfer,

            das letzte WHERE habe ich durch ein HAVING ersetzt (ansonsten hat er gemerkt 'Unknown column fzgid'), so dass es jetzt so aussieht:

            Müsste dann nicht auch folgendes funktionieren?

            SELECT db.*  
            ,      fzgflotte.ID       AS fzgid  
            ,      teil2.IntPrintDate AS zlb_datum  
            ,      teil2.NumZLB       AS zlb_nr  
              FROM #__vdm_db        db  
              JOIN #__vdm_teil2     teil2     ON db.IntTeil2ID = teil2.ID  
              JOIN #__vdm_fzgflotte fzgflotte ON (db.IntFzgFlotteID = fzgflotte.ID AND db.IntStatus = fzgflotte.IntStatus AND fzgflotte.FIN = '$fin')  
             WHERE db.IntStatus = 'G'
            

            MfG,
            EKKi

            --
            sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
            1. Nabend EKKi,
              auch dieser Query funktioniert tadellos.
              Danke & Gruß,
              Jan

              1. Mahlzeit berlinsurfer,

                auch dieser Query funktioniert tadellos.

                Und welche ist jetzt übersichtlicher? :-)

                MfG,
                EKKi

                --
                sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
                1. Hi EKKi,
                  ich persönlich tendiere zu HAVING. Die schicken Joins machen aber auch was her :-)
                  Kurzer Gruß,
                  Jan

                  1. Mahlzeit berlinsurfer,

                    ich persönlich tendiere zu HAVING.

                    HAVING ist im Regelfall aber ein ziemlicher Performance-Fresser (hast Du Dir die entsprechenden Unterschiede mal mittels EXPLAIN anzeigen lassen?), da diese Einschränkungen immer erst vorgenommen werden, *NACHDEM* die gesamte Ergebnismenge einmal ermittelt wurde.

                    Die schicken Joins machen aber auch was her :-)

                    Vor allem aber sieht man sofort, wie die einzelnen Tabellen denn nun eigentlichen miteinander verknüpft sind ... mit einer Unterabfrage dazugeschummelte Daten, die dann später ganz am Schluss durch ein HAVING wieder eingegrenzt werden, sind in bezug auf Übersichtlichkeit nicht wirklich hilfreich.

                    MfG,
                    EKKi

                    --
                    sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
                    1. Nabend, EKKi,
                      du hast mich überzeugt. Bei meinem Query hatte er 3700 Zeilen in der Ergebnismenge, die dann per HAVING verkürzt wurden und bei deiner waren es genau 3. Werde jetzt also versuchen, alle meine Queries hinsichtlich Joins zu optimieren.
                      Vielen Dank für deine Hilfe & die Erklärungen !
                      Gruß aus der verregneten Hauptstadt,
                      Jan

                      1. Noch eine kurze Frage:
                        es kann sein, dass die IntTeil2ID null ist (d. h. es gibt noch kein Teil 2 Dokument), kann ich das irgendwie in sql abfangen ? Dann dürfte es kein Join auf #__vdm_teil2 geben und der Query müsste so aussehen:

                        SELECT  
                                      coc.*,  
                                      fzgflotte.ID       AS fzgid,  
                                      FROM #__vdm_coc       coc  
                                      JOIN #__vdm_fzgflotte fzgflotte ON (coc.IntFzgFlotteID = fzgflotte.ID AND coc.IntStatus = fzgflotte.IntStatus AND fzgflotte.FIN = '$fin')  
                                      WHERE coc.IntStatus = 'G'  
                        
                        

                        Ich hab's jetzt mit PHP gelöst (sprich zwei Queries), mich würde eine Lösung in SQL aber interessieren. Danke schonmal,
                        Jan

                        1. Nachtrag: Eventuell irgendwas mit EXISTS als Subquery und dann if... then ?

                        2. Mahlzeit berlinsurfer,

                          es kann sein, dass die IntTeil2ID null ist (d. h. es gibt noch kein Teil 2 Dokument), kann ich das irgendwie in sql abfangen ?

                          Ja. Prinzipiell empfehle ich Dir dazu die Lektüre der Artikel "Einführung in Joins" und "Fortgeschrittene Jointechniken" ... im konkreten Fall könnte ein LEFT OUTER JOIN helfen:

                          SELECT coc.*  
                          ,      fzgflotte.ID       AS fzgid  
                          ,      teil2.IntPrintDate AS zlb_datum  
                          ,      teil2.NumZLB       AS zlb_nr  
                            FROM #__vdm_coc              coc  
                            JOIN #__vdm_fzgflotte        fzgflotte ON (coc.IntFzgFlotteID = fzgflotte.ID AND coc.IntStatus = fzgflotte.IntStatus AND fzgflotte.FIN = '$fin')  
                            LEFT OUTER JOIN #__vdm_teil2 teil2     ON coc.IntTeil2ID = teil2.ID  
                           WHERE coc.IntStatus = 'G'
                          

                          Ich hab's jetzt mit PHP gelöst (sprich zwei Queries),

                          Du hast das Problem nicht gelöst, sondern nur verlagert. :-)

                          MfG,
                          EKKi

                          --
                          sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
                          1. Ja. Prinzipiell empfehle ich Dir dazu die Lektüre der Artikel "Einführung in Joins" und "Fortgeschrittene Jointechniken" ... im konkreten Fall könnte ein LEFT OUTER JOIN helfen:

                            Danke, EKKi,
                            da werde ich mal reinschauen.
                            Gruß,
                            Jan