Cap: SQL-Gruppierung mit mehreren Ergebnissen je Gruppe

Hi,

ich stehe gerade vor einem Problem, dass ich sonst immer mit Subqueries löse, aber leider steht mir hier nur ein MySQL 4.0 - Server zur Verfügung, also muss ich wohl anders auskommen.

Die Tabelle die ich abfrage hat einige tausend Datensätze. Jeder dieser Datensätze hat in der gleichen Spalte einen von maximale 15 verschiedenen Werten. Wenn ich also alle Datensätze nach dieser Spalte gruppiere, würde ich 15 Ergebnisse bekommen, quasi eines von jedem Typ dieser Spalte. Ich möchte aber eben nicht eines, sondern drei von jedem Typ haben. Da ich nicht sicher sein kann, dass von jedem Typ auch wirklich drei Datensätze vorhanden sind, kann das Ergebniss dieser Abfrage also irgendwo zwischen 0 und 45 Ergebnissen liegen. Man könnte jetzt 15 Abfragen machen oder eine entsprechende Subquery. Letzteres geht nicht wegen dem alten MySQL-Server und ersteres finde ich ziemlich unelegant, bzw. auch unperformant. Irgendwelche Ideen wie ich das hier hinkriegen kann?

Danke und Gruß
Cap

  1. Hallo

    ich stehe gerade vor einem Problem, dass ich sonst immer mit Subqueries löse, aber leider steht mir hier nur ein MySQL 4.0 - Server zur Verfügung, also muss ich wohl anders auskommen.

    eine wichtige Information.

    Deine Problembeschreibung habe ich leider nicht verstanden. Könntest Du bitte Dein Problem anhand eines kleinen Beispiels mit ein paar Datensätzen vorstellen. D.h. Eine Ausgangstabelle mit vielleicht 10 Datensätzen und die gewünschte Zieltabelle - mit Begründung, warum diese genauso aussieht, wie sie aussieht.

    Kannst Du ggf. mit einer temporären Tabelle arbeiten?

    Freundliche Grüße

    Vinzenz

    1. Hallo,

      Deine Problembeschreibung habe ich leider nicht verstanden. Könntest Du bitte Dein Problem anhand eines kleinen Beispiels mit ein paar Datensätzen vorstellen. D.h. Eine Ausgangstabelle mit vielleicht 10 Datensätzen und die gewünschte Zieltabelle - mit Begründung, warum diese genauso aussieht, wie sie aussieht.

      Gerne. Als einfaches Beispiel ist dies die Ausgangstabelle mit zwei Spalten a und b.

      -------------
      | a |   b   |
      -------------
      | 0 | Row 0 |
      | 0 | Row 1 |
      | 0 | Row 2 |
      | 1 | Row 3 |
      | 1 | Row 4 |
      | 2 | Row 5 |
      | 2 | Row 6 |
      | 2 | Row 7 |
      | 2 | Row 8 |
      | 2 | Row 9 |
      -------------

      Ich möchte nun jeweils bis zu drei Ergebnisse mit dem gleichen Wert in Spalte 'a' bekommen, sortiert nach Spalte a und b. Das Ergebnis hier wäre also:

      -------------
      | a |   b   |
      -------------
      | 0 | Row 0 |
      | 0 | Row 1 |
      | 0 | Row 2 |
      | 1 | Row 3 |
      | 1 | Row 4 |
      | 2 | Row 5 |
      | 2 | Row 6 |
      | 2 | Row 7 |
      -------------

      Da der Wert '0' in Spalte 'a' nur dreimal vorkommt, werden alle Datensätze mit diesem Wert gewählt, die Datensätze mit dem Wert '1' ebenfalls, da es weniger als drei sind. Von Datensätzen mit dem Wert '2' werden nur die ersten drei gewählt.

      Dazu ist wichtig, dass die Werte '0','1' und '2' nicht direkt im Query angegeben werden, sondern der Query alle vorhandenen Werte der Spalte 'a' selbst gruppiert, weil später noch weitere Werte hinzukommen werden.

      Ich kann das jetzt wie erwähnt lösen, indem ich erste alle einmaligen Werte aus Spalte 'a' abfrage und dann danach auf die Ergebnisse einen  auf drei Datensätze limitierten Query absetze, aber das ist meiner Meinung nach ziemlich unsauber.

      Kannst Du ggf. mit einer temporären Tabelle arbeiten?

      Es wäre schöner, wenn es ohne geht.

      Viele Grüße
      Cap

      1. yo,

        Ich kann das jetzt wie erwähnt lösen, indem ich erste alle einmaligen Werte aus Spalte 'a' abfrage und dann danach auf die Ergebnisse einen  auf drei Datensätze limitierten Query absetze, aber das ist meiner Meinung nach ziemlich unsauber.

        habe dir bereits geschrieben, dass du mit der UNION Klausel ein einzige abfrage zusammen basteln kannst. meiner meinung nach geht es nicht anders, da sich sonst die LIMIT Klausel nicht auf die jeweiligen gruppierungen bezieht, sondern auf das gesamtergebnis.

        die andere möglichkeit wäre, erst mal eine DISTINCT abfrage auf die entsprechende spalte abzufeuern, um alle unterschiedlichen werte zu bekommen, und dann pro record eine weiter abfrage, die dir die ersten drei datensätze der jeweiligen gruppierung gibt.

        Ilja

        1. Hallo,

          habe dir bereits geschrieben, dass du mit der UNION Klausel ein einzige abfrage zusammen basteln kannst. meiner meinung nach geht es nicht anders, da sich sonst die LIMIT Klausel nicht auf die jeweiligen gruppierungen bezieht, sondern auf das gesamtergebnis.

          Ich weiß, danke, ich habe dir aber noch nicht darauf geantwortet, weil ich noch hoffe, dass es auch in der 4.0 Version eine andere Möglichkeit gibt. Über Union wäre ich nämlich auch gezwungen vorher erstmal alle möglichen Werte der Spalte 'a' abzufragen. Wie im letzten Posting beschrieben, möchte ich das aber vermeiden.

          die andere möglichkeit wäre, erst mal eine DISTINCT abfrage auf die entsprechende spalte abzufeuern, um alle unterschiedlichen werte zu bekommen, und dann pro record eine weiter abfrage, die dir die ersten drei datensätze der jeweiligen gruppierung gibt.

          Ja, das hatte ich ja schon aufgeführt. Ich möchte aber nach Möglichkeit einen saubereren Weg finden.

          Gruß
          Cap

          1. yo,

            Ich weiß, danke, ich habe dir aber noch nicht darauf geantwortet, weil ich noch hoffe, dass es auch in der 4.0 Version eine andere Möglichkeit gibt. Über Union wäre ich nämlich auch gezwungen vorher erstmal alle möglichen Werte der Spalte 'a' abzufragen. Wie im letzten Posting beschrieben, möchte ich das aber vermeiden.

            auch bei einer version 4.1+ kann ich mir schwer eine andere lösung vorstellen, selbst mit unterabfragen stelle ich mir das schwierig vor. letztlich müsste auch dabei die limit klausel auf die jeweilige gruppierung greifen und das kann ich im moment nicht erkennen.

            Ja, das hatte ich ja schon aufgeführt. Ich möchte aber nach Möglichkeit einen saubereren Weg finden.

            die lösungen, die ich dir genannt habe sind sauber, da fehlerfrei. wenn du zuerst alle gruppen abrufst und dann eine UNION abfrage zusammenstellt, zum beispiel über PHP, dann hast du damit insgesamt zwei abfragen, die 100% das richtige ergebnis liefern wird. kann nicht erkennen, was daran unsauber ist.

            Ilja

  2. yo,

    Man könnte jetzt 15 Abfragen machen oder eine entsprechende Subquery. Letzteres geht nicht wegen dem alten MySQL-Server und ersteres finde ich ziemlich unelegant, bzw. auch unperformant. Irgendwelche Ideen wie ich das hier hinkriegen kann?

    eventuell kannst du die UNION KLausel verwenden, falls man bei mysql die LIMIT Klausel auf jede einzelne abfrage innerhalb der UNION Anweisung anwenden kann. wird halt nur ziemlich lang die eine abfrage.

    Ilja