JOINs (ich bin zu blöd)

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

  • JOINs (ich bin zu blöd)

    Hallo,

    erstmal vielen Dank an alle, die hier im Forum so fleißig schreiben! Ihr habt mir schon oft geholfen

    Das mit den JOINs habe ich (glaube ich) im Prinzip verstanden. Aber irgendwie bekomme ich das in meinem Fall nicht hin

    Hier mal das Script, von dem ich bis vor kurzem noch dachte, dass es das ist, was ich brauche:

    PHP-Code:
    $result mysql_query("SELECT artist FROM artists 
                           WHERE letter = '
    {$HTTP_GET_VARS['letter']}
                           ORDER BY artist LIMIT 
    {$HTTP_GET_VARS['astart']}, 30");
    while (
    $row mysql_fetch_object($result))
       {
          
    $artist $row->artist;

          
    $result2 mysql_query("SELECT artist FROM Artikel 
                                  WHERE artist = '
    $artist' AND bestand > 0 
                                  OR artist2 = '
    $artist' AND bestand > 0 
                                  OR artist3 = '
    $artist' AND bestand > 0 
                                  OR artists like '% 
    $artist %' AND bestand > 0");
          
    $num2    mysql_numrows($result2);

          if (
    $num2 0)
            {
            echo 
    "<a href='artist-show.php?artist=$artist>$artist</a> ($num2 items)<br>";
            }
       } 
    Habe der Übersichtlichkeit halber gekürzt. Das bisherige Ergebnis ist hier anzuschauen: http://www.reduktivemusiken.de/shop2/artist-index.php

    Was ich nicht bedacht habe ist, dass keine 30 "Artists" mehr gelistet werden, wenn $num2 = 0 ist. Was nicht nur unschön ist, sondern in Einzelfällen dazu führen kann, dass die letzten gar nicht mehr gelistet werden...

    Ich habe es bisher leider nicht hinbekommen die SQL-Abfrage innerhalb der Schleife in die ursprüngliche einzubauen. Liegt es vielleicht daran, dass es gar kein JOIN ist den ich hier brauche?

    Wäre schön wenn mir jemand das an meinem Beispiel erklären kann.

    Dank in voraus
    Dieter (PHP/SQL-Anfänger)

  • #2
    mach mal so:
    Code:
    select a.artist from artists a inner join artikel b on a.artist=b.artist
       where a.letters = ... and b.bestand ... b.artist2 ...
       order by ...
       limit ....
    setze Klammer bei where-Bedingung richtig ein, dann bekommst du auch richtiges Ergebnis; überall, wo $artist steht, ersetzt du mit a.artist, bei dem letzten wende den + operator an, um das Argument für like zusammenzubauen

    Kommentar


    • #3
      wenn Du das mit den Joins kapiert hast, warum machste dann kein join?
      Beantworte nie Threads mit mehr als 15 followups...
      Real programmers confuse Halloween and Christmas because OCT 31 = DEC 25

      Kommentar


      • #4
        hui, das ging ja schnell

        muss mich jetzt um die kinder kümmern. ich probier es morgen. sieht schon mal vielversprechend aus.

        (hab den INNER JOIN also vom Prinzip her nicht verstanden )

        @ MelloPie:
        berechtigte frage.
        antwort:
        weil meine versuche alle gescheitert sind und ich zum weiterarbeiten ein erstmal funktionierendes script brauchte. mein fehler: ich habe die fehlversuche frustriert gelöscht und konnte sie deshalb nicht posten...
        Zuletzt geändert von dieter2; 08.01.2007, 21:19.

        Kommentar


        • #5
          Da bin ich wieder.

          So sieht die Abfrage jetzt aus:
          PHP-Code:
          $result mysql_query("SELECT a.artist FROM artists a
          INNER JOIN Artikel b
          ON a.letter = '
          {$HTTP_GET_VARS['letter']}'
          WHERE (b.artist=a.artist) AND (b.bestand > 0)
                OR (b.artist2=a.artist) AND (b.bestand > 0)
                OR (b.artist3=a.artist) AND (b.bestand > 0)
                OR (b.artists LIKE '% '+a.artist+' %') AND (b.bestand > 0)
          GROUP BY a.artist
          ORDER BY a.artist
          LIMIT 
          {$HTTP_GET_VARS['astart']}$ds_anzahl")
          while (
          $row mysql_fetch_object($result))
             {... 
          Habe, denke ich, alle Varianten an Klammersetzung bei der WHERE-Bedingung ausprobiert. Auch alle Klammern noch einmal zusammen zu klammern.
          Die Abfrage von b.bestand macht er nicht. Es werden immer auch alle Musiker (artist) gelistet, bei denen bestand = 0 ist.
          Gleiches passiert, wenn ich "b.bestand > 0" bei der ON-Bedingung mit rein schreibe (was aufgrund der Datenmenge die Performance stark beeinflusst).
          Eine Idee was ich falsch mache?

          Kommentar


          • #6
            was soll der Unfug: ON a.letter = '{$HTTP_GET_VARS['letter']}' ?

            weisst du überhaupt was in ON anzugeben ist? wenn nicht

            Kommentar


            • #7
              Zugegeben, da habe ich rumprobiert. aber Du wirst lachen, da komme ich (von der b.bestand-Abfrage mal abgesehen) zum gewünschten Ergebnis.
              mit
              ON (b.artist = a.artist OR b.artist2 = a.artist OR b.artist3 = a.artist)
              WHERE ((a.letter = '{$HTTP_GET_VARS['letter']}')
              AND ...

              ignoriert er die Bedingung komplett

              mit
              ON a.artist = b.artist

              wie Du es beschrieben hast, genauso. mit dem Unterschied, dass viele Datensätze nicht mehr berücksichtigt werden.

              zum besseren Verständnis hier mal eine genauere beschreibung von dem, was ich will:

              der link: http://reduktivemusiken.de/shop2/art...x.php?letter=A
              (letter "A" ist ausgewählt)

              besagte Tabellen in der Datenbank

              artists
              | id | artist | letter |

              Artikel
              | id | artist | artist2 | artist3 | artists | bestand |
              (ohne die Spalten, die hier nicht abgefragt werden)

              artists/letter wird vorher für das Menü abgefragt (was auch hervoragend funktioniert).
              Es sollen aber nicht alle Daten aus artists/artist mit gewähltem letter angezeigt werden, sondern nur diejenigen, die in Artikel in artist, artist2 oder artist3 stehen oder u.a. in artists.
              Und hier soll noch einmal selektiert werden: nur die Datensätze mit bestand>0 sollen berücksichtigt werden.

              beispiel:
              artists
              | id | 1
              | artist | Audible Pain
              | letter | A
              ----
              | id | 2
              | artist | Mundkrach
              | letter | M

              Artikel
              | id | 1
              | artist | Audible Pain
              | artist2 |
              | artist3 |
              | artists |
              | bestand | 1
              ----
              | id | 2
              | artist | Mundkrach
              | artist2 | Audible Pain
              | artist3 |
              | artists |
              | bestand | 0
              ------

              "Audible Pain" soll gelistet werden, denn die Soloveröffentlichung hat bestand>0. Ausgabe bei Auswahl letter=A:
              Audible Pain (1 items)

              "Mundkrach" soll bei Auswahl letter=M nicht gelistet werden, da bestand=0 ist.

              --
              Das funktionierte mit meinem ursprünglichen Skript bereits. Aber die Ausgabe auf mehreren Seiten (LIMIT) hat da natürlich nicht richtig funktioniert...

              Das Script, wie es bei dem Link aktuell ist:
              PHP-Code:
                          $result mysql_query("SELECT a.artist FROM ".$PREFIX."_artists a
                 INNER JOIN "
              .$PREFIX."_Artikel b
                 ON (b.artist = a.artist OR b.artist2 = a.artist OR b.artist3 = a.artist)
                 WHERE ((a.letter = '
              {$HTTP_GET_VARS['letter']}')
                    AND (b.artist=a.artist AND b.bestand > 0)
                    OR (b.artist2=a.artist AND b.bestand > 0)
                    OR (b.artist3=a.artist AND b.bestand > 0)
                    OR (b.artists LIKE '% '+a.artist+' %' AND b.bestand > 0))
                 GROUP BY a.artist
                 ORDER BY a.artist
                 LIMIT 
              {$HTTP_GET_VARS['astart']}$ds_anzahl");
              while (
              $row mysql_fetch_object($result))
                 {... 
              Das Ergebnis ist, wie man sieht, absolut nicht das gewünschte.

              Hoffe ich habe es verständlich ausgedrückt.

              Kommentar


              • #8
                Original geschrieben von dieter2
                ON (b.artist = a.artist OR b.artist2 = a.artist OR b.artist3 = a.artist)
                WHERE ((a.letter = '{$HTTP_GET_VARS['letter']}')
                AND (b.artist=a.artist AND b.bestand > 0)
                OR (b.artist2=a.artist AND b.bestand > 0)
                OR (b.artist3=a.artist AND b.bestand > 0)
                OR (b.artists LIKE '% '+a.artist+' %' AND b.bestand > 0))
                Na ja, gleichlautende Bedingungen im ON und im WHERE unterzubringen, kann doch wohl schon mal nicht sinn der Sache sein.

                Und warum du die Bestand-Bedingung auch jedes Mal abfragen willst, ist mir auch unverständlich.
                Ausserdem wäre die vielleicht besser bei HAVING untergebracht, als bei WHERE.

                Hast du dich mit dem Sticky Thread hier im Forum schon beschäftigt? Insb. auch die Links zu den Artikeln bei SELFHTML beachtet?
                Zuletzt geändert von wahsaga; 09.01.2007, 15:42.
                I don't believe in rebirth. Actually, I never did in my whole lives.

                Kommentar


                • #9
                  PHP-Code:
                  $result mysql_query("SELECT a.artist FROM artists a
                  INNER JOIN Artikel b
                  ON (b.artist = a.artist
                    OR b.artist2 = a.artist
                    OR b.artist3 = a.artist
                    OR b.artists LIKE '% '+a.artist+' %')
                  WHERE a.letter = '
                  {$HTTP_GET_VARS['letter']}'
                  GROUP BY a.artist
                  HAVING b.bestand > 0
                  ORDER BY a.artist
                  LIMIT 
                  {$HTTP_GET_VARS['astart']}$ds_anzahl"
                  ok, danke!
                  jetzt sieht das ergebnis schon wieder besser aus.
                  aber lasse ich b.bestand>0 in der WHERE-Bedingung stehen, wird sie weiterhin ignoriert

                  steht sie so wie oben in der HAVING kommt folgende Fehlermeldung:
                  Unknown column 'b.bestand' in 'having clause'


                  die spalte existiert aber garantiert und wird auch so geschrieben. wahrscheinlich wird sie bei WHERE dann auch nicht gefunden.
                  eine idee warum? ein syntax-fehler?

                  p.s.: um die links kümmer ich mich später. insbesondere um die artist- übergabe (sonder- und leerzeichen)
                  Zuletzt geändert von dieter2; 10.01.2007, 15:42.

                  Kommentar


                  • #10
                    jetzt bin ich anscheinend komplett an meine grenzen gestoßen...
                    die abfrage schaut jetzt so aus:
                    PHP-Code:
                    $result mysql_query("SELECT a.artist, b.bestand FROM artists a
                    INNER JOIN Artikel b
                    ON (b.artist1 = a.artist
                      OR b.artist2 = a.artist
                      OR b.artist3 = a.artist
                      OR b.artists LIKE '% '+a.artist+' %')
                    WHERE a.letter = '
                    {$HTTP_GET_VARS['letter']}'
                    GROUP BY a.artist
                    HAVING b.bestand > 0
                    ORDER BY a.artist
                    LIMIT 
                    {$HTTP_GET_VARS['astart']}$ds_anzahl"
                    und funktioniert auch fast gut.
                    aber eben nur fast: es werden nicht alle artists gelistet und ich habe auch herausgefunden warum.
                    habe ich bei einem artist mehrere datensätze in tabelle Artikel und bei einem davon ist bestand=0 kann es passieren, dass der satz nicht ausgegeben wird.
                    das kann ich umgehen, indem ich die GROUP BY klausel raus nehme. aber dann werden alle artists 4-6x gelistet unabhängig davon, wie viele datensätze vom jeweiligen vorhanden sind

                    da stellt sich mir die frage, ob ich mit INNER JOIN überhaupt auf dem richtigen weg bin? oder habe ich etwas noch immer nicht richtig verstanden?

                    versuch schon seit knapp 3,5 stunden das prob zu knacken...
                    HIIILFEEE!!!

                    Kommentar


                    • #11
                      NOCH MAL NEU

                      habe die ganze abfrage noch einmal neu gebastelt:
                      PHP-Code:
                      $result mysql_query("SELECT a.artist, COUNT(b.bestand) AS items
                      FROM artists a, Artikel b
                      WHERE a.letter = '
                      {$HTTP_GET_VARS['letter']}'
                        AND (b.artist1 = a.artist
                        OR b.artist2 = a.artist
                        OR b.artist3 = a.artist
                        OR b.artists LIKE '% '+a.artist+' %')
                        AND b.bestand>0
                      GROUP BY a.artist
                      HAVING items>0
                      ORDER BY a.artist
                      LIMIT 
                      {$HTTP_GET_VARS['astart']}$ds_anzahl"
                      diesmal ohne JOIN und komme leider zum selben ergebnis

                      http://reduktivemusiken.de/shop2/art...x.php?letter=A

                      hatte eigentlich erwartet (erhofft), dass der COUNT die WHERE-Bedingung berücksichtigt.
                      die zahl am ende jeder ausgabe ist das COUNT-ergebnis. wollte eigentlich die zahl davor als ergebnis haben, die aus der abfrage in der folgenden schleife kommt (siehe 1. beitrag).
                      wenn ich es so hinbekomme hätte es den vorteil, dass ich die 2. abfrage spare und sich die performance erhöht.

                      sieht jemand einen denkfehler? oder habe ich schon wieder etwas nicht verstanden
                      Zuletzt geändert von dieter2; 12.01.2007, 14:06.

                      Kommentar


                      • #12
                        Dass das so kompliziert ist, liegt an deinem komischen Datenbankdesign...

                        logischer wäre folgender Aufbau:

                        Code:
                        Tabelle artists
                        -- id
                        -- name
                        
                        Tabelle artikel
                        -- id
                        -- bestand
                        (-- ev. name...)
                        
                        Tabelle lookup
                        -- artikel_id
                        -- artist_id
                        Das mit der extra Letter-Spalte ist auch unglücklich. Besser wäre es mit Stringfunktionen, z.b. LEFT().

                        Dann könntest du einfach so tun:

                        SELECT artists.name FROM artists INNER JOIN lookup ON artists.id = artist_id INNER JOIN artikel ON artikel_id = artikel.id WHERE LEFT(artists.name,1) = '$letter' AND bestand > 0

                        Oder ähnlich. Das wäre viel schlüssiger.
                        Zuletzt geändert von ministry; 12.01.2007, 14:20.
                        ich glaube

                        Kommentar


                        • #13
                          spalte letter wird bleiben. denn so kann ich rubriken einbauen, die zeichenunabhängig sind. eine band nennt sich z.b. [-hyph-] und ich möchte kein "[" im menü haben. der soll entweder bei "H" oder bei "OTHER" stehen. und magazine entziehen sich auch der reinen buchstabenzuweisung.

                          tabelle lookup klingt recht einfach, auch wenn sie min. 3-4 artikel_id-spalten brauchen wird damit die aufteilung auf der artist-show.php funktioniert. ist aber ein kleineres prob. was mir weniger daran gefällt ist, dass ich dann keine updates mehr per csv-datei machen kann. ist aber auch nicht das schlimmste.
                          das schlimmste wird es sein die bestehenden fast 1000 datensätze anzupassen...

                          wenn du oder wer anders noch eine idee hat, wie ich die jetzige abfrage hinbekomme (mit oder ohne JOIN), würde das sääähr helfen.

                          ansonsten habe ich wohl noch sehr viel arbeit vor mir...

                          Kommentar

                          Lädt...
                          X