Lukas.: mysql: Mehrfacheinträge, Sonderfälle

Guten Tag, schöne Pfingsten,

Ich suche doppelte Einträge einer Artikelliste:

SELECT Artikelnummer , Artikelbezeichnung , Lieferant , COUNT( ID ) AS cnt
FROM artikel
GROUP BY Lieferant,Artikelnummer
HAVING cnt >1

Zeigt mir Anzahl und Artikel an, der mehrfach vorhanden ist. Nun würde ich mir aber gerne die Einträge anzeigen lassen, in denen der Artikel-VK der mehrfachen Einträge unterschiedlich ist.

Also könnte ein Ergebnis so aussehen:


12345,Artikel1,Lieferant1,12.50
12345,Artikel1,Lieferant1,11.50
78345,Artikel5,Lieferant3,22.50
56345,Artikel5,Lieferant3,32.50
usw.

Wie komme ich an diese Einträge?

L.

  1. Hello,

    hast Du es schon mal mit DISTINCT ausprobiert?

    Die Bezeichung der Spalte mit ID ist für mich verwirrend. Da hätte ich angenommen, dass das der Primary Unique Key wäre...

    Liebe Grüße
    Tom S.

    --
    Es gibt nichts Gutes, außer man tut es
    Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
  2. Tach!

    Ich suche doppelte Einträge einer Artikelliste:

    SELECT Artikelnummer , Artikelbezeichnung , Lieferant , COUNT( ID ) AS cnt
    FROM artikel
    GROUP BY Lieferant,Artikelnummer
    HAVING cnt >1
    

    Zeigt mir Anzahl und Artikel an, der mehrfach vorhanden ist.

    Eine GROUP-BY-Abfrage, bei der weitere Felder als in der GROUP-BY-Klausel angegeben ohne Aggregatfunktion in der SELECT-Klausel verwendet werden, wird nur von MySQL toleriert. Die nicht eindeutig lösbare Frage dabei wäre nämlich, aus welchem der Datensätze der Gruppe soll der Feldinhalt genommen werden? Das geht nur dann problemlos, wenn die Inhalte alle gleich sind, weil MySQL sich irgendeinen Datensatz nimmt. Dann hätte man aber auch darüber gruppieren können.

    Nun würde ich mir aber gerne die Einträge anzeigen lassen, in denen der Artikel-VK der mehrfachen Einträge unterschiedlich ist.

    Erstell eine zweite Abfrage, mit dem Ergebnis der ersten als Bedingung. Eine Subquery in einem IN() schwebt mir da als Lösung vor. Das erfordert aber, dass die Subquery nur ein Feld liefert.

    dedlfix.

    1. Die nicht eindeutig lösbare Frage dabei wäre nämlich, aus welchem der Datensätze der Gruppe soll der Feldinhalt genommen werden? Das geht nur dann problemlos, wenn die Inhalte alle gleich sind, weil MySQL sich irgendeinen Datensatz nimmt. Dann hätte man aber auch darüber gruppieren können.

      Habe ich mir schon gedacht, dass mysql sich zufällig einen Feldinhalt schnappt.

      Erstell eine zweite Abfrage, mit dem Ergebnis der ersten als Bedingung. Eine Subquery in einem IN() schwebt mir da als Lösung vor.

      Auch schon versucht, hat aber nicht geklappt.

      Das erfordert aber, dass die Subquery nur ein Feld liefert.

      Kann doch eigentlich in diesem Fall nicht, oder? Welches Feld solte das denn sein?

      L.

      1. Tach!

        Erstell eine zweite Abfrage, mit dem Ergebnis der ersten als Bedingung. Eine Subquery in einem IN() schwebt mir da als Lösung vor.

        Auch schon versucht, hat aber nicht geklappt.

        Warum nicht?

        Das erfordert aber, dass die Subquery nur ein Feld liefert.

        Kann doch eigentlich in diesem Fall nicht, oder? Welches Feld solte das denn sein?

        Es muss ein eindeutiger Inhalt sein, mit dem du genau die gewünschten Datensätze selektieren kannst. Vielleicht die Artikelnummer?

        dedlfix.

        1. Es muss ein eindeutiger Inhalt sein, mit dem du genau die gewünschten Datensätze selektieren kannst. Vielleicht die Artikelnummer?

          Nein, das passt nicht. Verschiedene Lieferanten könnten identische Artikelnummern haben. Nur die Kombi aus Lieferant und Artikelnummer könnte/sollte eindeutig sein. Problem: Das sind sie ja gerade nciht, daher meine Abfrage.

          L.

          1. Hello,

            ich frage mich nur, was Dir die Abfrage nützen soll, wenn Du die Zeilen nicht eineindeutig voneinander unterscheiden kannst. MMn ist die Abfrage hochgradig wertlos.

            Du solltest erst einmal im Klartext genau definieren, was Du eigentlich wissen willst aus deiner Datenbank.

            Liebe Grüße
            Tom S.

            --
            Es gibt nichts Gutes, außer man tut es
            Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
            1. Nein, Tom, die Abfrage ist nicht nutzlos.

              Du solltest erst einmal im Klartext genau definieren, was Du eigentlich wissen willst aus deiner Datenbank.

              Gerne. Ich habe einen Datenbestand, bei dem in einer Artikelliste viele Einträge doppelt oder mehrfach vorhanden sind. Ich glaube aber, dass der Grossteil hiervon aus einem doppelten Importvorgang resultieren. Das muss ich aber prüfen. Daher möchte ich die Mehrfachartikel unterscheiden in die absolut identischen, von denen ich dann in Schritt 2 einfach einen herauslöschen kann und diejenigen, die tatsächlich unterschiedlich angelegt wurden (dieses leck ist inzwischen natürlich geschlossen) und hierbei einen unterschiedlichen VK haben. Diese Artikel muss ich mir genauer ansehen, daher benötige ich die Query.

              L.

              1. Hello,

                gibt es da keine Spalte mit Create-Date? Dann würde ich die mal schnellstens ergänzen. ;-)
                Ein gewisser Meta-Overhead in DB-Tabellen kann einem manchmal nämlich den Arsch retten!

                BTW:
                Eine solche Nachfrage ohne die Create-Statements der betroffenen Tabellen führt meistens zu geplatzten Glaskugeln, aber selten zu einem sinnvollen Ergebnis :-P

                Liebe Grüße
                Tom S.

                --
                Es gibt nichts Gutes, außer man tut es
                Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
                1. gibt es da keine Spalte mit Create-Date? Dann würde ich die mal schnellstens ergänzen. ;-)
                  Ein gewisser Meta-Overhead in DB-Tabellen kann einem manchmal nämlich den Arsch retten!

                  Doch, klar gibts die. Aber ich kann auch nicht einfach hiernach löschen.

                  BTW:
                  Eine solche Nachfrage ohne die Create-Statements der betroffenen Tabellen führt meistens zu geplatzten Glaskugeln, aber selten zu einem sinnvollen Ergebnis :-P

                  Das stimmt aber nicht. Bisher wurde mir hier mit einem Prozentsatz > 95% sinnvoll geholfen (auch von Dir, Kollege ;) )

                  1. Hello,

                    ich schließe jetzt aus deinen Ausführungen, dass es sich nicht um eine ständig verfügbare Abfrage handeln soll, sondern um eine Reparaturmaßnahme? Da wäre es durchaus zumutbar, in mehreren Stufen zu arbeiten - also mit temporären Tabellen, oder ähnlichen, also welchen, die später wieder gelöscht werden können.

                    Suche Dir also erst alle Datensätze zusammen, die kontrolliert werden müssen. Vergiss nicht, dabei den Primärschlüssel mit zu übertrgen. Und dann kannst Du in der zweiten Stufe die Bearbeitung vorbereiten.

                    So, wie sich das bisher liest (Du stellst uns ja nicht alle möglichen Kriterien zur Verfügung!), lässt sich keine verlässliche Fehlerbedingung definieren. Du musst die Zeilen zu doppelten Artikeln also manuell prüfen!?

                    Liebe Grüße
                    Tom S.

                    --
                    Es gibt nichts Gutes, außer man tut es
                    Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
                    1. Hi Tom,

                      genauso gehe ich gerade vor.

                      Danke für die Hilfe,

                      L.

          2. Tach!

            Es muss ein eindeutiger Inhalt sein, mit dem du genau die gewünschten Datensätze selektieren kannst. Vielleicht die Artikelnummer?

            Nein, das passt nicht. Verschiedene Lieferanten könnten identische Artikelnummern haben. Nur die Kombi aus Lieferant und Artikelnummer könnte/sollte eindeutig sein.

            Das weißt du, aber woher weiß ich denn das?

            Eine einfach klingender Versuch wäre ein CONCAT_WS() aus Lieferant und Artikelnummer, sowohl in der Subquery als auch vor dem IN(). Das läuft dann aber auf einen Full Table Scan hinaus, also bei Massendaten à la Amazon-Business eher nicht zu gebrauchen.

            Ansonten fällt mir da nur ein komplexes Gebilde mit Join ein. Deine Query als Subselect im JOIN mit FROM auf ebenjene Tabelle. Da dann Lieferant und Artikelnummer als Joinbedingung.

            dedlfix.

  3. Hi,

    SELECT Artikelnummer , Artikelbezeichnung , Lieferant , COUNT( ID ) AS cnt
    FROM artikel
    GROUP BY Lieferant,Artikelnummer
    HAVING cnt >1
    

    Zeigt mir Anzahl und Artikel an, der mehrfach vorhanden ist. Nun würde ich mir aber gerne die Einträge anzeigen lassen, in denen der Artikel-VK der mehrfachen Einträge unterschiedlich ist.

    Ok, wenn die Preise unterschiedlich sind, ist der min(preis) unterschiedlich von max(preis). Damit könnte man die having-Klausel erweitern um

    AND MIN(preis) <> MAX(preis)

    Um die verschiedenen Preise angezeigt zu bekommen, bietet sich bei mysql group_concat(preis) an.

    Hab grad kein mysql verfügbar - kann sein, daß MIN(preis) und MAX(preis) noch ins select rein müssen, damit sie im having verfügbar sind.

    cu,
    Andreas a/k/a MudGuard

    1. Ok, wenn die Preise unterschiedlich sind, ist der min(preis) unterschiedlich von max(preis). Damit könnte man die having-Klausel erweitern um

      AND MIN(preis) <> MAX(preis)

      Das ist aber eine pfiffige Idee, danke. Und sie funktioniert auch, ich habs gerade versucht.

      Um die verschiedenen Preise angezeigt zu bekommen, bietet sich bei mysql group_concat(preis) an.

      Wie wird das verwendet? Edit: Schon gesehen, einfach im SELECT (Kann mann den Seperator austauschen?)

      Hab grad kein mysql verfügbar - kann sein, daß MIN(preis) und MAX(preis) noch ins select rein müssen, damit sie im having verfügbar sind.

      Nein, muss nicht.

      L.

      1. Hi,

        Um die verschiedenen Preise angezeigt zu bekommen, bietet sich bei mysql group_concat(preis) an.

        Wie wird das verwendet? Edit: Schon gesehen, einfach im SELECT (Kann mann den Seperator austauschen?)

        weiß ich nicht, mußt Du in die Doku gucken.

        Ach ja, für die IDs der betroffenen Datensätze könntest Du das auch machen. Dann hast Du sie zumindest schon mal, wenn auch mehrere in einer Spalte.

        Aber daraus lassen sich ja mit wenig Aufwand (String aufsplitten an den Kommata) die einzelnen IDs wieder rausholen.

        Hab grad kein mysql verfügbar - kann sein, daß MIN(preis) und MAX(preis) noch ins select rein

        müssen, damit sie im having verfügbar sind.

        Nein, muss nicht.

        Ok, da war ich mir nicht sicher.

        cu,
        Andreas a/k/a MudGuard

  4. Hallo,

    warum wird bei:

    SELECT Artikelnummer , Artikelbezeichnung , Lieferant , COUNT( ID ) AS cnt
    FROM artikel
    GROUP BY Lieferant,Artikelnummer
    HAVING cnt >1
    

    nicht erfasst, dass es auch Artikelnummern, wie:

    − . "" (Leereichen), usw. gibt?

    Oder anders, wie muss ich meine WQuery verändern, damit diese auch erfasst werden?

    L.

    1. Tach!

      warum wird bei: [...] nicht erfasst, dass es auch Artikelnummern, wie:

      − . "" (Leereichen), usw. gibt?

      Mir fällt kein Grund ein, warum das nicht der Fall sein sollte. NULL nimmt eine Sonderstellung ein, aber alle anderen Zeichenfolgen sind einfach nur Zeichenfolgen.

      Reduzier den Fall mal auf die kleinstmögliche Tabelle und gib der ein paar Datensätze, mit denen man das Problem nachvollziehen kann.

      dedlfix.

      1. Mir fällt kein Grund ein, warum das nicht der Fall sein sollte. NULL nimmt eine Sonderstellung ein, aber alle anderen Zeichenfolgen sind einfach nur Zeichenfolgen.

        Reduzier den Fall mal auf die kleinstmögliche Tabelle und gib der ein paar Datensätze, mit denen man das Problem nachvollziehen kann.

        Gerne, dedlfix,

        'kan ich aber erst heute abend machen, weil ich "auf dem Sprung" bin.

        Wird also nachgeliefert.

        L.

        1. Tach!

          Reduzier den Fall mal auf die kleinstmögliche Tabelle und gib der ein paar Datensätze, mit denen man das Problem nachvollziehen kann.

          Gerne, dedlfix,

          'kan ich aber erst heute abend machen, weil ich "auf dem Sprung" bin.

          Wird also nachgeliefert.

          Das ist weniger für mich, sondern erstmal für dich, um zu sehen, ob das Problem nachstellbar ist. Daran kann man erkennen, ob es ein allgemeines Problem ist oder, wenn es nicht nachvollziehbar ist, eher an den spezifischen Umständen des Originals liegt.

          dedlfix.

          1. Habs doch noch flugs reduziert und siehe da, Du hast (natürlich) recht. Leerzeichen werden gen auso behandelt. Ursache im Original war, dass alle Leereinträge nicht denselben Lieferanten hatten, daher gehörten sie natürlich nicht zur Ergebnismenge.

            L.