Knud Schröder: (MySQL) brauche Hilfe bei komplizierter(?) Abrage

Hallo,

ich hab ein Problem mit einer für mich komplizierten Abfrage.

Das Problem ist, dass ich in einer Tabelle in einem Feld 4stellige Artikelnummern durch Komma getrennt drinstehen habe.
Also:
Feldname: artikel
Beispielinhalt: 1001,2345,8765,3333

Dabei schwankt die Anzahl der Artikel im Feld zwischen 0 und x.

Jetzt möchte ich eine Abfrage generieren, die mir eine Liste der vorkommenden Artikelnummern bringt, sortiert nach der Anzahl.

Gibt es eine Möglichkeit innerhalb der Abfrage das Artikel-Feld aufzusplitten und die Einzelteile zu zählen?
Wie stelle ich es am einfachsten an, wenn's nicht geht (was ich befürchte)?

Gruß und Dank,

Knud

  1. hi Knud,

    Das Problem ist, dass ich in einer Tabelle in einem Feld 4stellige Artikelnummern durch Komma getrennt drinstehen habe.

    der aufbau deiner tabelle ist meiner meinung nicht so geschickt. deine tabelle widerspricht der 1. Normalform. das ist nun kein weltuntergang, aber ich würde dir raten, für jede artikelnummer einen extra datensatz zu benutzen.

    das hört sich ein wenig nach einer tabelle für eine bestellung eines kunden an und soll alle artikel auflisten, die er bestellt hat. ich schätze mal, du hast eine tabelle für keunden und eine für artikel. die beiden tabellen stehen in einer beziehung n:m und sollten somit in einer beziehungstabelle (bestellungen) miteinander verknüpft werden. dabei würde sich an bieten, die artikelnummer, die kundennummer und das bestelldatum als zusammengesetzten schlüssel für die bestelltabelle zu nehmen. jede bestellung eines artikels druch einem kunden and einem tag würde damit einen datensatz ergeben

    Dabei schwankt die Anzahl der Artikel im Feld zwischen 0 und x.

    diese variation würde dann wegfallen, du hast also immer nur einen artikel pro datensatz in der bestelltabelle

    Jetzt möchte ich eine Abfrage generieren, die mir eine Liste der vorkommenden Artikelnummern bringt, sortiert nach der Anzahl.

    gehen wir mal weiter von meiner anahme aus, würde du nun die tabelle bestellung nach der kundennummer grouppieren (group by) und eine aggregatfunktion anwenden, die die anzahl der artikel zählt, nämlich sum (artikelnummer)

    Gibt es eine Möglichkeit innerhalb der Abfrage das Artikel-Feld aufzusplitten und die Einzelteile zu zählen?

    das würde auch gehen, halte ich aber für keine gute lösung. ob es direkt mit mysql geht, will ich mal offen lassen, aber mit mit php oder perl klappt es

    Ilja

    1. hi Knud,

      Das Problem ist, dass ich in einer Tabelle in einem Feld 4stellige Artikelnummern durch Komma getrennt drinstehen habe.

      der aufbau deiner tabelle ist meiner meinung nicht so geschickt. deine tabelle widerspricht der 1. Normalform. das ist nun kein weltuntergang, aber ich würde dir raten, für jede artikelnummer einen extra datensatz zu benutzen.

      Tja, ich weiß, die Struktur ist nicht so dolle und es wäre sinnvol gewesen, für jede Artikelnummer einen Satz zu nehmen.
      Aber so ist das mit gewachsenen Strukturen, wenn man nochmal von vorne anfangen könnte, würde man es anders machen.
      Jetzt muss ich erstmal die Struktur so hinnehmen.

      das hört sich ein wenig nach einer tabelle für eine bestellung eines kunden an und soll alle artikel auflisten, die er bestellt hat.

      Haarscharf :) Es soll eine Artikel-Hitliste ergeben.
      Die Kunden sind Techniker und die Artikel Ersatzteile. Also eine TopTen-Liste der am häufigsten benötigten Ersatzteile.

      Jetzt möchte ich eine Abfrage generieren, die mir eine Liste der vorkommenden Artikelnummern bringt, sortiert nach der Anzahl.

      gehen wir mal weiter von meiner anahme aus, würde du nun die tabelle bestellung nach der kundennummer grouppieren (group by) und eine aggregatfunktion anwenden, die die anzahl der artikel zählt, nämlich sum (artikelnummer)

      Einfache count(*) ... group by Abfragen bekomme ich auch hin ;-), aber wie gesagt, leider kann ich das ja nicht anwenden, da ich die Struktur der Tabelle nicht anpacken kann.
      Es sei denn ich würde erst eine Dummy-Tabelle mit den Werten erzeugen und darüber dann wieder die Abfrage laufen lassen. Das ist mein momentaner Lösungsgedanke.

      Gibt es eine Möglichkeit innerhalb der Abfrage das Artikel-Feld aufzusplitten und die Einzelteile zu zählen?

      das würde auch gehen, halte ich aber für keine gute lösung. ob es direkt mit mysql geht, will ich mal offen lassen, aber mit mit php oder perl klappt es

      Php wäre auch ganz gut, aber ich hab da meine Probleme wie ich das lösen könnte.
      Ich müsste wohl ein zweidimensionales Array aufbauen
      array[x][1] = Artikelnummer und
      array[x][2] = Menge
      und anschließend das Array wieder der Größe nach nach array[x][2] sortieren.
      Alles soweit theoretisch, da ich mit Arrays innerhalb von PHP nicht sooo firm bin.

      Gruß und Dank,

      Knud

      1. hi Knud,

        Tja, ich weiß, die Struktur ist nicht so dolle und es wäre sinnvol gewesen, für jede Artikelnummer einen Satz zu nehmen.
        Aber so ist das mit gewachsenen Strukturen, wenn man nochmal von vorne anfangen könnte, würde man es anders machen.
        Jetzt muss ich erstmal die Struktur so hinnehmen.

        anderer vorschlag: wenn die strukturen so gewachsen sind, kannst du vielleicht parallel arbeiten, sprich ein wenig an der alten struktur und gleichzeitig die neue aufbauen ? der punkt ist der, dass "unschöne" strukturen dich irgendwann mehr zeit und energie + knete kosten, als wenn du es neu strukturiren würdest. die alten daten lassen sich bestimmt in die neue strukturen importieren. aber das kommt sicherlich immer darauf an, was alles an den alten strukturen mit dranne hängt.

        Haarscharf :) Es soll eine Artikel-Hitliste ergeben.
        Die Kunden sind Techniker und die Artikel Ersatzteile. Also eine TopTen-Liste der am häufigsten benötigten Ersatzteile.

        ahh, dann musst du den group by über die artikel machen und nicht über die kunden. aber die sind ja zusammengepackt. das ist unschön. ;-)

        Es sei denn ich würde erst eine Dummy-Tabelle mit den Werten erzeugen und darüber dann wieder die Abfrage laufen lassen. Das ist mein momentaner Lösungsgedanke.

        das hört sich schon mal gut an. das problem ist, mysql kennt zwar zeichen-funktionen, mit den du die artikel in ihre bestandteile auflösen kannst. aber die sind meiner meinung nach hierfür nicht so sehr geeignet, mit fällt keine ein, ohne größeren aufwand. vieleicht hat jemand anders eine funktion unter mysql dafür parat.

        Php wäre auch ganz gut, aber ich hab da meine Probleme wie ich das lösen könnte.
        Ich müsste wohl ein zweidimensionales Array aufbauen
        array[x][1] = Artikelnummer und
        array[x][2] = Menge

        php halte ich für die bessere lösung. aber meine frage dazu, wo steht den die anzahl der jeweiligen bestellten artikel, die bestellt wurden ?

        Ilja

        1. Php wäre auch ganz gut, aber ich hab da meine Probleme wie ich das lösen könnte.
          Ich müsste wohl ein zweidimensionales Array aufbauen
          array[x][1] = Artikelnummer und
          array[x][2] = Menge

          php halte ich für die bessere lösung. aber meine frage dazu, wo steht den die anzahl der jeweiligen bestellten artikel, die bestellt wurden ?

          Ich habs jetzt doch über PHP mit mehrdimensionalen assoziativen Arrays gelöst. Hab mich durchgewurschtelt und sieht eigentlich ganz gut aus.
          Ich vertrau noch nicht so ganz dem Ergebnis :)

          Gruß und Dank,

          Knud

          1. hi Knud,

            Ich habs jetzt doch über PHP mit mehrdimensionalen assoziativen Arrays gelöst. Hab mich durchgewurschtelt und sieht eigentlich ganz gut aus.

            ob nun mehrdimensionale arrays erforderlich sind, kann ich noch nicht so ganz nachvollziehen. ich würde es mit zwei abfragen machen:

            1. alle artikel aus der datenbank holen und sie in einem assoziativen array artikel[artikelnummer] speichern und initialisiere es mit den wert 0.

            2. alle datensätze der berstellung mit den artikelmix auslesen. dann gehe ich diese datensätze durch, indem ich sie anhand des tokens komma trenne und erhöhe das entsprechende artikel um eins, indem ich einfach das array artikel mit artikell [hier der wert der trennung] ++ anspreche

            Ich vertrau noch nicht so ganz dem Ergebnis :)

            vertrau der macht

            Ilja

  2. Hello Knud,

    Beispielinhalt: 1001,2345,8765,3333

    select count(ARTIKEL) from LISTE where find_in_set("1001",ARTIKEL);

    So könntest Du nach jeder Artikelnummer einzeln suchen und diese zählen. Hat aber den Nachteil, dass nur die Sätze gezählt werden. Wenn also irgendwo eine Artikelnummer zweimal im Satz steht, wird das nur als Eins gezählt.

    Mit PHP kann man sich natürlich ein Zählwerkzeug bauen. Das braucht aber viel Speicher. Vieviele Datensätze hast Du denn? Allerdings teilen sich MySQL und PHP den Speicherbedarf. MySQL trägt den Bärenanteil:

    Select auf das Artikelfeld:

    Select ARTIKEL from LISTE;

    Dann in PHP

    $liste = array();
    while ($satz = mysql_fetch_assoc($res))
    {
      $artikel=explode($satz["ARTIKEL"];
      foreach ($artikel as $key => $val)
      {
        $liste[$val]++;
      }
    }

    mysql_free_result($res); ## nicht vergessen.

    echo <"pre">;
    print_r($liste);
    echo <"/pre">;

    So könnte es klappen. Ist aber eben die Holzhackermethode.
    Änder lieber Deine Datenstruktur.
    Das kannst Du dann auch auf eine ähnliche Weise machen.
    In der foreach()-Anweisung musst DU dann eben für jede Satznummer des Stammsatzes einen Satz mit $id, $val in einer neunen Tabelle erzeugen.

    Grüße

    Tom