Mehrfache Ausgabe bei SQL-Abfrage aus 2 Tabellen

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

  • Mehrfache Ausgabe bei SQL-Abfrage aus 2 Tabellen

    Hallo, ich hab eine Frage.
    Ich habe zwei Tabellen:
    fragen (ca 500 Einträge) und fragen_solved (ca 40.000 Einträge)

    Meine Abfrage bisher lautete (Bsp.):
    Code:
    SELECT a.ID, a.Ersteller, a.Frage_QT, a.LVL_Code, a.erster, a.tester
    FROM frage a
    WHERE 
    a.ID < 101 OR
    a.erster LIKE 'NICK' OR
    (a.Ersteller LIKE 'NICK' OR a.Ersteller LIKE 'NICK & %' OR a.Ersteller LIKE '% & NICK' OR a.Ersteller LIKE '% & NICK & %')
    ORDER BY ID DESC
    Nun will ich die Abfrage modifizieren, aber das haut irgendwie alles zusammen.
    Ich würde die Abfrage gerne wiefolgt ändern:
    Code:
    WHERE (a.ID = b.LVL AND b.UID = 'NICK') OR
    (a.`Ersteller` LIKE 'NICK' OR a.`Ersteller` LIKE 'NICK & %' OR a.`Ersteller` LIKE '% & NICK' OR a.`Ersteller` LIKE '% & NICK & %')
    mit frage_solved as b..

    Die Abfrage dauert ewig lang, und liefert ca 1.000.000+ Einträge, anstatt ca 150, was man aber mit SELECT INSTINCT abfangen kann, die Dauer der Abfrage jedoch nicht.

    Nach probieren bin ich drauf gekommen, dass bei der ersten Abfrage, wenn ich FROM frage a, frage_solved b hinschreibe, ohne dass auf b eine Bedingung oder Ausgabe zutrifft, sich die Abfrage seehr verlängert, und die Ausgaben wieder mehrfach vorkommen und in die Millionen gehen.

    Das zwingt natürlich meinen Server in die Knie und ist sicher nicht ideal, leider kann ich aber keinen Fehler entdecken, vor allem den Grund nicht, wieso sich dieselbe Abfrage (die 1.) so verlängert/ändert, wenn ich einfach eine Tabelle dazuschreibe, die zwar viele Einträge hat, aber nicht in die Abfrage weiters eingreift. Wäre toll, wenn mir wer helfen könnte,
    danke
    Zuletzt geändert von SoS; 25.05.2010, 18:19.

  • #2
    Bitte Code ordentlich und sauber formatieren. Niemand scrollt gern 2 Meter nach rechts.

    Kommentar


    • #3
      Zitat von h3ll Beitrag anzeigen
      Bitte Code ordentlich und sauber formatieren. Niemand scrollt gern 2 Meter nach rechts.
      sry, dachte code bricht auch um ^^ ist behoben

      Kommentar


      • #4
        Mach einen sauberen INNER JOIN.

        Die Theta-Style schreibweise ist schwer lesbar und verleitet zu Fehlern. Im blödesten Fall machst du einen Cross-Join und die Ergebnismenge vervielfacht sich.

        Code:
        SELECT      t1.foo, t2.bar
        FROM        tabelle1 t1
        INNER JOIN  tabelle2 t2 ON ( t2.id = t1.fremd_id )
        WHERE       t1.foo > 1 AND t2.bar LIKE 'abc%'
        Zuletzt geändert von h3ll; 25.05.2010, 17:22.

        Kommentar


        • #5
          Zitat von SoS Beitrag anzeigen
          was man aber mit SELECT INSTINCT abfangen kann, die Dauer der Abfrage jedoch nicht.
          Natürlich - die massive Anzahl an Datensätzen muss ja erst mal ermittelt werden, bevor überhaupt mit DISTINCT Duplikate rausgeworfen werden können.


          Informiere dich über JOINs.
          SELFHTML Artikel / Datenbanken
          I don't believe in rebirth. Actually, I never did in my whole lives.

          Kommentar


          • #6
            Hallo,

            kannst du mal bitte erläutern, was du eigentlich vor hast und die Felder den beiden Tabellen mit einer kurzen Erklärung auflisten? Die create-table-Statements könnten auch schon helfen.

            Übrigens: Wenn du etwas mit LIKE vergleichst, ohne Platzhalter zu verwenden, solltest du lieber gleich = nehmen.

            Gruß,

            Amica
            Zuletzt geändert von AmicaNoctis; 25.05.2010, 17:25.
            [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
            Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
            Super, danke!
            [/COLOR]

            Kommentar


            • #7
              Zitat von AmicaNoctis Beitrag anzeigen
              Hallo,

              kannst du mal bitte erläutern, was du eigentlich vor hast und die Felder den beiden Tabellen mit einer kurzen Erklärung auflisten?
              Also, ich hatte bis jetz immer LVL_max gespeichert, und alle LVL darunter ausgegeben. Da die LVL nun aber nicht mehr der Reihe nach gemacht werden, muss ich für jedes LVL extra Speichern, ob USER das schon gelöst hat.
              Dazu wird in frage_solved die User-ID in UID und das entsprechende LVL gespeichert.
              Danach sollen die LVL abgefragt werden, die schon von USER gelöst wurden, also in frage_solved als UID|LVL vorkommen.
              Zudem sollen noch die LVL angezeigt werden, die von ihm erstellt wurden.
              Dies steht in frage unter "ersteller". Problem hier, er kann alleine oder zumehrt drinnen stehen, wo sie mit " & " getrennt sind. Ist er zumehr drinnen, kann er am Anfang stehen (USER & %), in der Mitte (% & USER & %) oder am Ende (% & USER). Wenn ihr hierführ eine bessere Abfrage wisst, bin ich gerne dafür offen
              Die LVL sind in frage gespeichert und haben id als ID.

              Ich hoffe, das ist halbwegs verständlich.
              Ich probier nebenbei schon mit Joins rum jetz, danke

              Kommentar


              • #8
                Zitat von SoS Beitrag anzeigen
                Dies steht in frage unter "ersteller". Problem hier, er kann alleine oder zumehrt drinnen stehen, wo sie mit " & " getrennt sind. Ist er zumehr drinnen, kann er am Anfang stehen (USER & %), in der Mitte (% & USER & %) oder am Ende (% & USER).
                Ein grober Fehler im Datenbankdesign. In einer Spalte sollte nicht mehr als eine Information stehen. Das macht das ganze natürlich unnötig kompliziert und performance-aufwändig.

                Kommentar


                • #9
                  Zitat von h3ll Beitrag anzeigen
                  Ein grober Fehler im Datenbankdesign. In einer Spalte sollte nicht mehr als eine Information stehen. Das macht das ganze natürlich unnötig kompliziert und performance-aufwändig.
                  Das mag wohl sein, ist aber leider nicht mein Hauptproblem jetzt
                  Ich glaub langsam verstanden zu haben, wieso ich so viele Rückgaben bekomme.
                  Reduzieren wird den Code mal aufs wesentliche:
                  Code:
                  SELECT        *
                  FROM         frage a
                  INNER JOIN    frage_solved b ON (a.ID = b.LVL) 
                  WHERE        b.UID = '63' OR
                          a.einsteller = 'SoS'
                  ORDER BY     ID DESC
                  So bekomm ich mal korrekterweise alle LVL, die User 63 gelöst hat.
                  Die 2. Bedingung jedoch wirft mir jedes LVL, das die Bedingung erfüllt, mehrfach raus, da das LVL ja für jeden User usw da steht, aufgrund des JOINS.
                  Kann man nicht irgendwie die beiden Abfragen getrennt voneinander machen, und das Ergebnis wieder zusammenfügen? Einzeln funktionieren die Abfragen nämlich wunderbar und ohne Auslastung.
                  Bsp: (Pseudocode)
                  Code:
                  SELECT        *
                  FROM         frage a
                  WHERE       a.einsteller = 'SoS'
                  
                  AND
                  
                  SELECT       a.*
                  FROM         frage a, frage_solved b
                  WHERE       b.UID='63' AND a.ID = b.LVL

                  Kommentar


                  • #10
                    Zitat von SoS Beitrag anzeigen
                    Die 2. Bedingung jedoch wirft mir jedes LVL, das die Bedingung erfüllt, mehrfach raus, da das LVL ja für jeden User usw da steht, aufgrund des JOINS.
                    Nein, aufgrund des schlechten Designs, denn eigentlich könnte man das prima filtern bzw. gruppieren. Da du dich aber weigerst, das als Ursache anzuerkennen, wirst du mit der schlechten Performance leben müssen.
                    [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
                    Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
                    Super, danke!
                    [/COLOR]

                    Kommentar


                    • #11
                      Im Code kommt die entsprechende Spalte doch garnicht mehr vor.
                      Dennoch aber die riesige Mehrfachausgabe jeder Zeile. Wie kann ich dem jetzt entgegen wirken?
                      Code:
                      SELECT        *
                      FROM         frage a
                      INNER JOIN    frage_solved b ON (a.ID = b.LVL) 
                      WHERE        b.UID = '63' OR
                              a.einsteller = 'SoS'
                      ORDER BY     ID DESC
                      Zuletzt geändert von SoS; 25.05.2010, 19:56.

                      Kommentar


                      • #12
                        GROUP BY …

                        Ansonsten musst du mal präziser werden und ein Beispiel wie es sein soll posten.
                        [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
                        Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
                        Super, danke!
                        [/COLOR]

                        Kommentar


                        • #13
                          Code:
                          frage
                          ID    |    ...    |    Einsteller
                          1                Max
                          2                SoS
                          3                Tom
                          4                SoS
                          5                SoS
                          
                          frage_solved
                          UID    |    LVL
                          63        1
                          63        2
                          63        3
                          50        1
                          50        2
                          50        3
                          50        4
                          50        5
                          Für den User SoS mit der ID 63 sollte nun 1,2,3 aus frage angezeigt werden, weil er diese gesolved hat, und 2,4,5 weil er diese eingestellt hat.

                          JOIN ich die beiden Tabellen, ergibt sich folgendes:

                          Code:
                          UID    |    LVL/ID    |    Einsteller
                          63        1        Max
                          63        2        SoS
                          63        3        Tom
                          50        1        Max
                          50        2        SoS
                          50        3        TOm
                          50        4        SoS
                          50        5        SoS
                          
                          SELECT            *
                          FROM             frage a
                          INNER JOIN      frage_solved b ON (a.ID = b.LVL) 
                          WHERE            b.UID = '63' OR
                                      a.einsteller = 'SoS'
                          ORDER BY         ID DESC
                          Aufgrund von UID=63 wird 1,2,3 ausgegeben
                          Aufgrund von Einsteller = SoS wird 2,2,4,5 ausgegeben.
                          In diesem Bsp wird jetzt nur ein Wert zuviel ausgegeben, aber in der Praxis, ist es leider um vielfaches mehr. Ein reduzieren mittels DISTINCT liefert zwar das gewünschte Ergebnis, aber es wird leider zulange gebraucht dafür, da der Einsteller eines LVL bei jedem User gezählt wird..
                          Mach ich noch was falsch?

                          PS: Formatierung leider bissl doof...

                          Kommentar


                          • #14
                            Sieh dir mal group by an (wie gesagt) und dazu noch group_concat.
                            [COLOR="DarkSlateGray"]Hast du die [COLOR="DarkSlateGray"]Grundlagen zur Fehlersuche[/color] gelesen? Hast du Code-Tags benutzt?
                            Hast du als URL oder Domain-Beispiele example.com, example.net oder example.org benutzt?
                            Super, danke!
                            [/COLOR]

                            Kommentar

                            Lädt...
                            X