Markus: 2 tabellen überprüfen

hallo!

folgende zeilen nutze ich, um die top 20 der gästebucheinträge meiner mitglieder zu suchen:

$r = database("SELECT ownerid FROM " . $dbpref . "guestbooks");
while ($u = mysql_fetch_assoc($r)) {
 $ownerid = $u['ownerid'];
 $temp[$ownerid]++;
}
arsort($temp);
echo "                <td valign="top">\n";
$i = 0;
foreach ($temp as $key => $value) {
 if ($i > 19) break;
 $r = database("SELECT * FROM " . $dbpref . "user WHERE userstatus > 0 AND id = $key");
 $u = mysql_fetch_assoc($r);
...

geht das auch einfacher mit einer verknüpfung der abfrage? wenn ja, wie? ich habe da etwas gelesen, aber nicht wirklich verstanden. danke!

  1. Halihallo Markus

    foreach ($temp as $key => $value) {
     if ($i > 19) break;

    müsste hier nicht if ($value > 19) break; stehen?

    $r = database("SELECT * FROM " . $dbpref . "user WHERE userstatus > 0 AND id = $key");
     $u = mysql_fetch_assoc($r);
    geht das auch einfacher mit einer verknüpfung der abfrage? wenn ja, wie? ich habe da etwas gelesen, aber nicht wirklich verstanden. danke!

    Ja, du bräuchtest einen Subselect (gibt's aber z. B. in mysql nicht). Falls subselects
    von deinem RDBMS nicht unterstützt werden, geht's IMHO nur über zwei/mehrere Queries.

    Viele Grüsse

    Philipp

    1. hallo philipp,

      Halihallo Markus
      müsste hier nicht if ($value > 19) break; stehen?

      ups, am ende der foreach steht noch folgendes:

      $i++;
      }
      damit ist es dann ok...

      Ja, du bräuchtest einen Subselect (gibt's aber z. B. in mysql nicht). Falls subselects
      von deinem RDBMS nicht unterstützt werden, geht's IMHO nur über zwei/mehrere Queries.

      bahnhof? chinesisch? also ist die lösung so schon ok?

      Viele Grüsse

      Philipp

      gruß

      markus

      1. Halihallo Markus

        müsste hier nicht if ($value > 19) break; stehen?

        ups, am ende der foreach steht noch folgendes:

        $i++;
        }

        Stimmt. Obwohl die Lösung über die DB besser (im Sinne von performance) ist.

        Ja, du bräuchtest einen Subselect (gibt's aber z. B. in mysql nicht). Falls subselects
        von deinem RDBMS nicht unterstützt werden, geht's IMHO nur über zwei/mehrere Queries.

        bahnhof? chinesisch? also ist die lösung so schon ok?

        Das folgerte ich fälschlicherweise, ja. Deine Lösung ist OK, jedoch mit dem Query meines
        zweiten Postings zu verbessern (das Sortieren und Einschränken der Ergebnismenge
        steigert die Performance). Ich ging fälschlicherweise davon aus, dass du auch die
        einzelnen Daten der Beiträge benötigst, dies ginge nicht ohne mehrere Queries oder
        Subselects (welche nicht in jedem DB implementiert sind). Wenn du nur die Top-20 Poster
        ausgeben willst, sollte der Query vom zweiten Posting funktionieren (unten die
        korrigierte Version).

        SELECT u.*, COUNT(gb.ownerid) AS 'count'
           FROM
              guestbook AS gb,
              user as u
           WHERE
              gb.ownerid=u.id
           GROUP BY
              gb.ownerid
           ORDER BY 'count' DESC
           LIMIT 0, 20

        Du machst einen GROUP BY ownerid/id und zählst die Anzahl Postings jedes users. Mit dem
        ORDER BY sortierst du diese und mit dem LIMIT 0, 20 selektierst du die ersten 20
        Einträge (das sind dann eben diejenigen, welche am meisten gepostet haben).

        Viele Grüsse

        Philipp

        1. Du machst einen GROUP BY ownerid/id und zählst die Anzahl Postings jedes users. Mit dem
          ORDER BY sortierst du diese und mit dem LIMIT 0, 20 selektierst du die ersten 20
          Einträge (das sind dann eben diejenigen, welche am meisten gepostet haben).

          Viele Grüsse

          Philipp

          hallo philipp,

          vielen dank!

          ich denke, dass ich das mit deiner erklärung verstehen werde...

          gruß

          markus

        2. SELECT u.*, COUNT(gb.ownerid) AS 'count'
             FROM
                guestbook AS gb,
                user as u
             WHERE
                gb.ownerid=u.id
             GROUP BY
                gb.ownerid
             ORDER BY 'count' DESC
             LIMIT 0, 20

          das klappt prima, aber ich würde auch gerne die ohne einträge noch hinten dran listen. geht das auch?

          user a - 15 einträge
          user b - 12 einträge
          user c - 3 einträge
          user d - 0 einträge

          gruß

          markus

          1. Halihallo Markus

            das klappt prima, aber ich würde auch gerne die ohne einträge noch hinten dran listen. geht das auch?

            Nicht in einem Query (ich hoffe, dass ich nicht schon wieder einen Denkfehler mache...),
            obwohl ich glaube, dass dein Vorhaben auch keinen Sinn ergibt. Du möchtest die Top-20
            Poster ausgeben, was haben da Poster mit 0 Postings zu suchen?
            Um noch alle Poster mit 0 Beiträgen auszugeben, benutze:

            SELECT u.*
               FROM
                  guestbook AS gb
                  LEFT OUTER JOIN user as u ON u.id=gb.ownerid
               WHERE
                  gb.ownerid = NULL

            dies ist meiner Meinung nach die schnellste Möglichkeit, lasse mich jedoch gerne
            korrigieren (bei einem Fehler im Query sowieso). Zur Implementierung: Einfach den zuvor
            geposteten Query ausführen, die Results anzeigen und dann den oben beschriebenen (und
            wieder ausgeben).
            Zum Query: Alle Poster auszugeben, die noch keinen Beitrag geschrieben haben ist
            gleichbedeutend mit der Aussage: Alle Poster ausgeben, welche _nicht_ mit mindestens
            einem Eintrag aus der gb - Tabelle verknüpft werden können. Dies kann man über einen
            LEFT OUTER JOIN erreichen, welcher eben die nicht in der anderen Tabelle existierenden
            Felder (bezogen auf die Kondition u.id=gb.ownerid) mit dem Wert NULL füllt. Auf diesen
            kannst du in dem WHERE (WHERE gb.ownerid=NULL) prüfen und bekommst so alle User zurück,
            welche noch keinen Beitrag geschrieben haben.

            Viele Grüsse

            Philipp

            1. Nicht in einem Query (ich hoffe, dass ich nicht schon wieder einen Denkfehler mache...),
              obwohl ich glaube, dass dein Vorhaben auch keinen Sinn ergibt. Du möchtest die Top-20
              Poster ausgeben, was haben da Poster mit 0 Postings zu suchen?
              Um noch alle Poster mit 0 Beiträgen auszugeben, benutze:

              es geht darum, dass ich zum einen die top20 anzeige (ohne die, die noch keinen eintrag haben) und dann über eine mitgliedergalerie, die nach verschiedenen kriterien neu sortiert werden kann, will ich immer alle mitglieder anzeigen lassen. daher sollen auch die mit 0 einträgen gezeigt werden...

              das problem ist jetzt, es müsste beides in einen query, weil ich immer 10 pro seite zeige und den limit daher auf $start,10 setze... das gelingt mir mit meinem verständnis aber nicht bei 2 queries...

              gruß

              markus

              1. Halihallo Markus

                das problem ist jetzt, es müsste beides in einen query, weil ich immer 10 pro seite zeige und den limit daher auf $start,10 setze... das gelingt mir mit meinem verständnis aber nicht bei 2 queries...

                Stimmt. Wenn du nach wie vor die Daten aus den Gästebucheinträgen nicht brauchst, kannst
                du folgenden Query benutzen:

                SELECT
                      u.*,
                      COUNT(gb.ownerid) AS count
                   FROM
                      user AS u
                      LEFT OUTER JOIN guestbook AS gb ON gb.ownerid=u.id
                   ORDER BY count
                   GROUP BY gb.ownerid
                   LIMIT $start, 10

                Damit erhälst du dann etwa folgendes:

                id   name  count
                   1 n1        3
                   2 n2        2
                   3 n3        0

                ist es das, wonach du suchst?

                Der LEFT OUTER JOIN (falls du den noch nicht kennst), brauchst du, um auch User
                anzuzeigen, welche gar nicht mit der Guestbook-Tabelle gejoined werden können, da sie
                gar keine Beiträge geschrieben haben. Alle Felder von Guestbook werden in dem Falle mit
                NULL gefüllt, was bei einem COUNT(gb.ownerid) zu einer '0' führt (also keine Beiträge).

                Viele Grüsse

                Philipp

                1. hallo philipp,

                  erstmla vielen dank für deine bemühungen, aber so ganz klappt dein query nicht.

                  SELECT
                        u.*,
                        COUNT(gb.ownerid) AS count
                     FROM
                        user AS u
                        LEFT OUTER JOIN guestbook AS gb ON gb.ownerid=u.id
                     ORDER BY count
                     GROUP BY gb.ownerid
                     LIMIT $start, 10

                  Damit erhälst du dann etwa folgendes:

                  id   name  count
                     1 n1        3
                     2 n2        2
                     3 n3        0

                  das wäre die perfekte lösung, ja... ;-)

                  ich habe den query jetzt etwas verändert, aber es geht noch immer nicht:

                  SELECT u.*, COUNT(gb.ownerid) AS 'count' FROM " . $dbpref . "guestbooks AS gb, " . $dbpref . "user AS u LEFT OUTER JOIN guestbooks AS gb ON gb.ownerid=u.id ORDER BY 'count' GROUP BY gb.ownerid LIMIT $start, 10

                  es erscheint der fehler:

                  Keine eindeutige(n) Tabelle/Alias: 'gb'

                  1. Halihallo Markus

                    erstmla vielen dank für deine bemühungen, aber so ganz klappt dein query nicht.

                    Der einzige Fehler, den ich in meinem Query gesehen habe ist, dass ich den ORDER BY vor
                    dem GROUP BY hatte (was zu einem Fehler führt). ;)

                    ich habe den query jetzt etwas verändert, aber es geht noch immer nicht:

                    Eben wegen deinen Veränderungen, schätze ich ;)

                    SELECT u.*, COUNT(gb.ownerid) AS 'count' FROM " . $dbpref . "guestbooks AS gb, " . $dbpref . "user AS u LEFT OUTER JOIN guestbooks AS gb ON gb.ownerid=u.id ORDER BY 'count' GROUP BY gb.ownerid LIMIT $start, 10

                    es erscheint der fehler:

                    Keine eindeutige(n) Tabelle/Alias: 'gb'

                    schau dir doch deinen Query mal an. Du hast zweimal guestbook in dem FROM-Kontainer und
                    beide hast du mit dem Alias gb verknüpft; ist klar, dass mysql dann reagiert...
                    Das erste FROM guestbooks AS gb brauchst du nicht, ich hatte da ja den LEFT OUTER JOIN
                    für die Tabelle guestbook eingeführt.

                    Viele Grüsse

                    Philipp

  2. Halihallo Markus

    [...]

    Ich hab zu weit gedacht; dachte fälschlicherweise, dass du auch die Gästebucheinträge
    brauchst. Hier der Query [bin grad gestresst, kann nachher noch erläutern, falls erwünscht]

    SELECT u.*, COUNT(*) AS 'count'
       FROM
          guestbook AS gb,
          user as u
       WHERE
          db.ownerid=u.id
       GROUP BY
          db.ownerid
       ORDER BY 'count'
       LIMIT 0, 20

    Viele Grüsse

    Philipp