mysql: Mehrfach vorhandene Einträge (aber mit Bedingung) finden
Pit
- sql
Hallo,
ich würde mich grad lieber um dieses Problem kümmern, aber es haben sich einige andere Aufgaben dazwischen gedrängt. Die meisten sind erledigt, aber eine habe ich noch.
Hierzu muß ich aus einer Tabelle mehrfache Einträge heraussuchen, was mir über diese Query gelingt:
SELECT ID , COUNT( ID ) AS cnt
FROM tabelle
GROUP BY ID
HAVING cnt >1
ORDER BY `cnt` ASC
Nun habe ich aber noch eine Bedingung zu erfüllen:
Die Tabelle hat eine Spalte "wert". Und ich würde gerne nur die mehrfachen Einträge finden, bei denen mehr als 1 Eintrag dieselbe Einstellung in der Spalte "wert" hat. Somit sollten bspw. keine Einträge gefunden werden, bei denen die "wert-Spalte" mit jeweils 1,2 und 3 gefüllt sind. Aber es solten die gefunden werden, bei denen die "wert-Spalte" 1,2, und 2 beinhaltet.
Wie ergänze ich die Query?
Pit
Hallo Pit,
du bist beim Gruppieren nicht auf eine Spalte begrenzt. Die Regeln beim Gruppieren sind:
Außer natürlich in MySQL. Der verwendet bei einer ungruppierten Spalte, die im SELECT steht, einfach den ersten Wert den er findet. Aber Standard ist das nicht.
Ob ein Gruppierbegriff einen Subselect enthalten darf, weiß ich nicht. Es wäre logisch, wenn es erlaubt wäre. Und es wäre eine nette Möglichkeit, den SQL Server zur Weißglut zu bringen.
Rolf
Hallo Rolf,
du bist beim Gruppieren nicht auf eine Spalte begrenzt.
- Gruppiert wird die Zeilenmenge, die von FROM und WHERE festgelegt wird.
- Gruppiert werden kann nach 1-N Gruppierbegriffen.
- Ein Gruppierbegriff kann eine Spalte der gruppierten Zeilenmenge sein, oder ein Ausdruck, der mit diesen Spalten gebildet wird
- Die Gruppierbegriffe dürfen direkt im SELECT als Ergebnisspalten aufgeführt werden.
- Was kein Gruppierbegriff ist, muss in einer Aggregatfunktion stehen (MIN, MAX, COUNT, etc).
Außer natürlich in MySQL. Der verwendet bei einer ungruppierten Spalte, die im SELECT steht, einfach den ersten Wert den er findet. Aber Standard ist das nicht.
Worauf bezieht sich Dein letzter Satz hier, d.h. was von den Punkten geht bei mysql nicht?
Pit
Hallo Pit,
das hast Du falsch verstanden, bei MYSQL geht MEHR als erlaubt ist.
Angenommen, du hast eine Tabelle Waren (Kategorie, Artikel, Preis). Dann ist SELECT Kategorie, Preis FROM Waren GROUP BY Kategorie
falsch. Du kannst SUM(PREIS), MIN(PREIS) oder COUNT(*) machen, aber keine ungruppierte Spalte angeben. In MYSQL schon, der nimmt dann einfach den Preis vom ersten Artikel den er findet. Zumindest meine ich das mal so gelesen zu haben.
Rolf
Tach!
das hast Du falsch verstanden, bei MYSQL geht MEHR als erlaubt ist.
Beschrieben im MySQL-Handbuch.
Angenommen, du hast eine Tabelle Waren (Kategorie, Artikel, Preis). Dann ist
SELECT Kategorie, Preis FROM Waren GROUP BY Kategorie
falsch. Du kannst SUM(PREIS), MIN(PREIS) oder COUNT(*) machen, aber keine ungruppierte Spalte angeben. In MYSQL schon, der nimmt dann einfach den Preis vom ersten Artikel den er findet. Zumindest meine ich das mal so gelesen zu haben.
Irgendeinen, nicht den ersten, denn dazu müsste die Menge definiert sortiert sein. Wenn man MySQL auf Standardkonformität einstellt, dann kann man eine solche Query trotzdem stellen, muss aber dazu die Aggregatfunktion ANY_VALUE() nehmen. Damit wird dann auch deutlich, dass da irgendwas kommt, nur nichts definiertes.
Das Verhalten ist für solche Fälle gedacht, wo die Gruppierung trotzdem eindeutige Werte liefert, beispielsweise bei nicht normalisierten Mengen, oder wenn eine Menge mit Dopplungen drin durch einen Join entstanden ist.
dedlfix.
Hallo dedlfix,
Irgendeinen, nicht den ersten, denn dazu müsste die Menge definiert sortiert sein.
Ich hatte damit mal rumprobiert. Es war immer der erste Wert, der bei einem unsortierten SELECT als erstes gekommen wäre. Deswegen schrieb ich "den ersten, den er findet". Das ist nicht zwingend der, der in der Table als erstes kommt, oder der erste in einer bestimmten Reihenfolge, sondern der, der im per FROM aufgespannten Zeilenprodukt zuerst angetroffen wird.
Jedenfalls ist das nichts, worauf man sich verlassen sollte, insofern hast Du natürlich recht.
Rolf
Wie ergänze ich die Query?
Ich gehe mal davon aus, dass es mit dieser Query überhaupt nicht gehen wird, sondern nur über einen Innerjoin. Aber auch dieser müßte noch ergänzt werden 😕
SELECT liste.ID
FROM tabelle liste
INNER JOIN (
SELECT ID
FROM tabelle
GROUP BY ID
HAVING COUNT(ID) > 1) dup ON liste.ID = dup.ID
GROUP BY ID
Pit
Hallo Pit,
wieso, das ist doch ein Inner Join (INNER ist für JOIN übrigens der Default, das Keyword kannst Du weglassen).
Aber was denn soll passieren - willst Du für die IDs mit Duplikaten alle Sätze anlisten? Wenn also die ID 4711 dreimal vorkommt, drei Sätze ausgeben? Dann solltest Du den letzten GROUP BY weglassen und vielleicht noch ein paar mehr Spalten ausgeben...
SELECT liste.ID, liste.wert, liste.dings, liste.bums
FROM tabelle liste
JOIN (SELECT ID, wert
FROM tabelle
GROUP BY ID, wert
HAVING COUNT(*) > 1) dup
ON liste.ID = dup.ID AND liste.wert = dup.wert
Rolf